Skip to main content
RapidDev - Software Development Agency
replit-integrationsStandard API Integration

How to Integrate Replit with Looker

To integrate Replit with Looker, store your Looker API client ID and client secret in Replit Secrets (lock icon πŸ”’), use the Looker SDK to authenticate and run queries against Looker Explores, and embed dashboards or surface BI data in your application. Looker uses a client ID and client secret pair for API 4.0 authentication. Use an Autoscale deployment for dashboard data APIs and Reserved VM for scheduled report generation.

What you'll learn

  • How to create Looker API credentials and store them in Replit Secrets
  • How to authenticate with the Looker API 4.0 using the Python SDK from Replit
  • How to run inline queries and retrieve data from Looker Explores programmatically
  • How to fetch Look and dashboard results via the Looker REST API from Node.js
  • How to use Looker's signed embed URLs for embedding dashboards in Replit-hosted applications
Book a free consultation
4.9Clutch rating ⭐
600+Happy partners
17+Countries served
190+Team members
Intermediate14 min read25 minutesAnalyticsMarch 2026RapidDev Engineering Team
TL;DR

To integrate Replit with Looker, store your Looker API client ID and client secret in Replit Secrets (lock icon πŸ”’), use the Looker SDK to authenticate and run queries against Looker Explores, and embed dashboards or surface BI data in your application. Looker uses a client ID and client secret pair for API 4.0 authentication. Use an Autoscale deployment for dashboard data APIs and Reserved VM for scheduled report generation.

Looker API Integration for BI Data and Dashboard Embedding

Looker is Google Cloud's enterprise business intelligence platform, used by data teams to define metrics in LookML and expose them as governed, reusable queries. For application developers, the Looker API opens up powerful capabilities: run arbitrary queries against Looker Explores and get results as JSON, fetch saved Look results on demand, generate signed embed URLs so users can view Looker dashboards inside your application, and trigger data downloads in various formats. From Replit, these capabilities let you build data-rich applications that surface Looker analytics without users needing direct Looker access.

Looker's API authentication uses a client ID and client secret tied to a Looker user account. Each Looker user can generate API credentials from their account settings β€” these credentials have the same data access permissions as the user they belong to. For application integrations, create a dedicated Looker service account (a Looker user created specifically for API access) with the minimum data permissions needed. Store the client ID and client secret in Replit Secrets.

The Looker SDK for Python (looker-sdk) and the REST API (accessible from any language with an HTTP client) both support the same capabilities. The Python SDK is the most ergonomic choice for Replit Python projects. For Node.js projects, the @looker/sdk package provides equivalent functionality. Both SDKs handle the OAuth 2.0 token flow automatically β€” you provide credentials once and the SDK manages token generation and renewal.

Integration method

Standard API Integration

Looker integrates with Replit through the Looker API 4.0 using client ID and client secret authentication. Your Replit server exchanges credentials for an access token via the Looker SDK, then makes API calls to run queries, fetch Look results, download dashboards, and retrieve explore data. Looker's Python and Node.js SDKs handle token management automatically.

Prerequisites

  • A Replit account with a Node.js or Python Repl ready
  • A Looker instance (Google Cloud Looker or Looker's original cloud) with API access enabled
  • A Looker user account with API credentials (Admin can generate these under Users β†’ Edit User β†’ API Credentials)
  • Looker API access enabled on your Looker instance (Admin β†’ General Settings β†’ API)
  • Python packages: looker-sdk, flask; Node.js packages: @looker/sdk, express

Step-by-step guide

1

Generate Looker API Credentials

Looker API credentials are generated per user from within the Looker application. The credentials consist of a Client ID and Client Secret that represent the Looker user's access. Log into your Looker instance. If you have Looker Admin access, navigate to Admin β†’ Users and find the user (or create a new service account user) that will be used for API access. Click 'Edit' on the user, then scroll down to 'API Keys'. Click 'New API Key' to generate a client ID and client secret. Copy both values immediately β€” the secret is shown once. For production integrations, create a dedicated Looker user (e.g., 'replit-api-service') with a role that grants only the data permissions your integration needs. Avoid using an admin user's credentials for API integrations β€” if the credentials are compromised, a scoped role limits the blast radius. Note your Looker instance URL: it will be in the format https://yourcompany.looker.com (Looker cloud) or https://your-internal-looker-host.com (self-hosted). This URL is needed to initialize the Looker SDK. Also note whether your instance uses Looker API 4.0 (recommended, all current instances) or 3.1 (legacy). API 4.0 is the current standard and is what the SDK defaults to.

Pro tip: If you are using Google Cloud Looker (the newer Looker Studio platform), the API credentials and authentication differ. These instructions cover Looker (the original BI platform), not Looker Studio (Google Data Studio replacement).

Expected result: You have a Looker API client ID and client secret. You know your Looker instance URL. The API user has appropriate data permissions for the Explores you intend to query.

2

Store Looker Credentials in Replit Secrets

Click the lock icon (πŸ”’) in the Replit sidebar to open the Secrets panel. Add the following secrets: LOOKER_BASE_URL: your Looker instance URL, e.g., https://yourcompany.looker.com. Include the protocol but no trailing slash. LOOKER_CLIENT_ID: the client ID from your Looker API credentials. LOOKER_CLIENT_SECRET: the client secret from your Looker API credentials. LOOKER_PORT: the Looker API port (typically 19999 for self-hosted instances, 443 for Looker cloud). If using Looker cloud, this may not be needed β€” the SDK will use port 443 by default. The Looker Python SDK can be configured using environment variables with specific names (LOOKERSDK_BASE_URL, LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET) or via a looker.ini file. Using Replit Secrets mapped to these SDK-specific variable names is the cleanest approach β€” the SDK will auto-configure from environment variables without any explicit initialization code. Replit's Secret Scanner monitors for credential patterns. Looker client secrets follow a specific format that the scanner may detect if accidentally included in code.

init-looker.py
1# Option 1: SDK reads from standard Looker env vars (set these as Replit Secrets)
2# LOOKERSDK_BASE_URL=https://yourcompany.looker.com
3# LOOKERSDK_CLIENT_ID=your_client_id
4# LOOKERSDK_CLIENT_SECRET=your_client_secret
5# LOOKERSDK_VERIFY_SSL=true
6
7# Option 2: Initialize SDK explicitly from custom secret names
8import os
9import looker_sdk
10from looker_sdk import models40 as models
11
12# Configure SDK with credentials from Replit Secrets
13sdk = looker_sdk.init40(
14 base_url=os.environ['LOOKER_BASE_URL'],
15 client_id=os.environ['LOOKER_CLIENT_ID'],
16 client_secret=os.environ['LOOKER_CLIENT_SECRET']
17)
18
19# Test connection
20me = sdk.me()
21print(f'Connected to Looker as: {me.display_name} ({me.email})')

Pro tip: If you name your Replit Secrets exactly LOOKERSDK_BASE_URL, LOOKERSDK_CLIENT_ID, and LOOKERSDK_CLIENT_SECRET, the Looker Python SDK will auto-configure from them without any explicit initialization code.

Expected result: Looker credentials are stored in Replit Secrets. The initialization test connects successfully and prints the Looker user's display name.

3

Query Looker Explores and Looks with Python SDK

The Looker Python SDK provides a comprehensive interface for running queries, fetching Look results, and accessing explore metadata. Install it in the Replit Shell: pip install looker-sdk flask. Two primary ways to fetch data from Looker: 1. Run inline query: construct a query with model, view, fields, filters, and limits, then call sdk.run_inline_query() to execute it immediately. 2. Fetch a Look: call sdk.run_look(look_id, result_format='json') to run a saved Look and get its results. For inline queries, the query object specifies which Looker Explore to query (model and view), which dimensions and measures to include (fields), and any filter conditions. The result_format parameter controls the output format β€” 'json' returns a list of row objects, 'json_detail' includes metadata, 'csv' returns comma-separated text. The Flask server below demonstrates both patterns with proper error handling. For production use, add caching to avoid running the same Looker query repeatedly β€” Looker queries can take several seconds to execute against large datasets.

looker_api.py
1# looker_api.py β€” Looker API client for Replit (Python)
2import os
3import json
4from flask import Flask, request, jsonify
5import looker_sdk
6from looker_sdk import models40 as models
7
8# Initialize SDK from Replit Secrets
9sdk = looker_sdk.init40(
10 base_url=os.environ['LOOKER_BASE_URL'],
11 client_id=os.environ['LOOKER_CLIENT_ID'],
12 client_secret=os.environ['LOOKER_CLIENT_SECRET']
13)
14
15app = Flask(__name__)
16
17@app.route('/api/query', methods=['POST'])
18def run_query():
19 """Run an inline Looker query."""
20 body = request.get_json()
21
22 try:
23 query = models.WriteQuery(
24 model=body['model'], # e.g., 'ecommerce'
25 view=body['view'], # e.g., 'orders'
26 fields=body.get('fields', []), # e.g., ['orders.count', 'orders.created_date']
27 filters=body.get('filters', {}), # e.g., {'orders.status': 'complete'}
28 limit=str(body.get('limit', 500))
29 )
30
31 results = sdk.run_inline_query('json', query)
32 return jsonify(json.loads(results))
33
34 except Exception as e:
35 return jsonify({'error': str(e)}), 500
36
37@app.route('/api/looks/<int:look_id>')
38def run_look(look_id):
39 """Fetch results of a saved Looker Look."""
40 result_format = request.args.get('format', 'json')
41
42 try:
43 results = sdk.run_look(look_id=look_id, result_format=result_format)
44 if result_format == 'json':
45 return jsonify(json.loads(results))
46 else:
47 return results, 200, {'Content-Type': 'text/csv'}
48 except Exception as e:
49 return jsonify({'error': str(e)}), 500
50
51@app.route('/api/dashboards/<int:dashboard_id>')
52def get_dashboard_info(dashboard_id):
53 """Get dashboard metadata and element list."""
54 try:
55 dashboard = sdk.dashboard(dashboard_id=str(dashboard_id))
56 return jsonify({
57 'title': dashboard.title,
58 'description': dashboard.description,
59 'element_count': len(dashboard.dashboard_elements or [])
60 })
61 except Exception as e:
62 return jsonify({'error': str(e)}), 500
63
64if __name__ == '__main__':
65 app.run(host='0.0.0.0', port=3000)

Pro tip: Looker query results are returned as a JSON string, not a Python dict. Use json.loads(results) to convert the string to a Python object before returning it with jsonify().

Expected result: POST /api/query with model, view, and fields returns query results from Looker as JSON. GET /api/looks/123 returns the results of saved Look 123.

4

Fetch Looker Data from Node.js

For Node.js Replit projects, the @looker/sdk package provides a JavaScript/TypeScript interface to the Looker API. Alternatively, you can use the Looker REST API directly with axios using token authentication. Install in the Replit Shell: npm install @looker/sdk @looker/sdk-node express. The @looker/sdk-node package provides the LookerNodeSDK that works in Node.js server environments (the @looker/sdk package alone is for browser use). Initialize it with your credentials from Replit Secrets. For simpler Node.js integrations, the REST API approach using axios is more straightforward: POST to /api/4.0/login with your client_id and client_secret to get an access token, then use the token in subsequent requests. This approach requires manual token refresh, while the SDK handles it automatically. The code below shows both patterns. The SDK approach is recommended for frequent API calls; the direct REST approach is fine for occasional queries.

looker.js
1// looker.js β€” Looker API client for Replit (Node.js)
2const axios = require('axios');
3const express = require('express');
4
5const LOOKER_BASE_URL = process.env.LOOKER_BASE_URL;
6const CLIENT_ID = process.env.LOOKER_CLIENT_ID;
7const CLIENT_SECRET = process.env.LOOKER_CLIENT_SECRET;
8
9if (!LOOKER_BASE_URL || !CLIENT_ID || !CLIENT_SECRET) {
10 throw new Error('Missing Looker credentials in Replit Secrets (lock icon πŸ”’)');
11}
12
13// Token cache
14let accessToken = null;
15let tokenExpiry = 0;
16
17async function getLookerToken() {
18 if (accessToken && Date.now() < tokenExpiry - 30000) return accessToken;
19
20 const response = await axios.post(`${LOOKER_BASE_URL}/api/4.0/login`, {
21 client_id: CLIENT_ID,
22 client_secret: CLIENT_SECRET
23 });
24
25 accessToken = response.data.access_token;
26 tokenExpiry = Date.now() + (response.data.token_ttl * 1000);
27 return accessToken;
28}
29
30async function lookerRequest(method, path, data = null) {
31 const token = await getLookerToken();
32 const config = {
33 method,
34 url: `${LOOKER_BASE_URL}/api/4.0${path}`,
35 headers: {
36 Authorization: `token ${token}`,
37 'Content-Type': 'application/json'
38 }
39 };
40 if (data) config.data = data;
41 const response = await axios(config);
42 return response.data;
43}
44
45const app = express();
46app.use(express.json());
47
48// Run an inline query
49app.post('/api/query', async (req, res) => {
50 const { model, view, fields, filters, limit = 500 } = req.body;
51 try {
52 // Create query
53 const query = await lookerRequest('POST', '/queries', { model, view, fields, filters, limit });
54 // Run query
55 const results = await lookerRequest('GET', `/queries/${query.id}/run/json`);
56 res.json(results);
57 } catch (err) {
58 res.status(500).json({ error: err.response?.data || err.message });
59 }
60});
61
62// Get a Look's results
63app.get('/api/looks/:lookId', async (req, res) => {
64 try {
65 const results = await lookerRequest('GET', `/looks/${req.params.lookId}/run/json`);
66 res.json(results);
67 } catch (err) {
68 res.status(500).json({ error: err.response?.data || err.message });
69 }
70});
71
72app.listen(3000, '0.0.0.0', () => console.log('Looker Node.js server running on port 3000'));

Pro tip: The Looker REST API uses 'token' (not 'Bearer') as the Authorization scheme: Authorization: token YOUR_ACCESS_TOKEN. Using 'Bearer' will result in a 401 error.

Expected result: POST /api/query returns Looker Explore results as a JSON array. GET /api/looks/123 returns the saved Look's current data. The token is cached and refreshed automatically.

Common use cases

Data API for Looker-Powered Dashboards

Build an Express or Flask API layer that runs Looker queries on request and returns results as JSON. Your frontend application calls this Replit API to get business metrics, chart data, and KPIs β€” without direct Looker access for end users. The Replit layer adds caching, authentication, and data transformation on top of raw Looker results.

Replit Prompt

Build a Flask API that accepts a metric name and date range, queries the corresponding Looker Explore using the Looker Python SDK, and returns aggregated results as JSON for a React dashboard.

Copy this prompt to try it in Replit

Embedded Dashboard Integration

Generate Looker SSO embed URLs from a Replit server to embed Looker dashboards in your application with signed authentication. Users view live, interactive Looker dashboards within your app's UI without needing their own Looker credentials.

Replit Prompt

Create an Express server that generates Looker signed embed URLs using the embed secret and returns them to the frontend, allowing authenticated users to view specific Looker dashboards embedded in the application.

Copy this prompt to try it in Replit

Scheduled Report Generator

Set up a Reserved VM Replit service that runs Looker queries on a schedule, formats the results into HTML or CSV reports, and distributes them via email or Slack. The service acts as a lightweight reporting automation layer on top of Looker's data.

Replit Prompt

Build a Python service that runs on a schedule, fetches weekly sales data from a Looker Look, formats it as a CSV, and sends it as an email attachment using SMTP β€” deploy as a Replit Reserved VM for continuous scheduling.

Copy this prompt to try it in Replit

Troubleshooting

401 Unauthorized when calling Looker API β€” 'Not authorized' error

Cause: The client ID or client secret is incorrect, or the Looker API is not enabled on your instance. Also occurs if the credentials belong to a user whose account is disabled.

Solution: In Looker Admin β†’ Users, verify the API user account is active. Go to Edit User β†’ API Keys to confirm the client ID matches what is in Replit Secrets. Re-generate API keys if uncertain. Also check Admin β†’ General Settings β†’ API is enabled for your Looker instance.

typescript
1# Test Looker login directly
2import os, requests
3response = requests.post(f'{os.environ["LOOKER_BASE_URL"]}/api/4.0/login', json={
4 'client_id': os.environ['LOOKER_CLIENT_ID'],
5 'client_secret': os.environ['LOOKER_CLIENT_SECRET']
6})
7print(response.status_code, response.json())

ValidationError or 'Unknown model' when running inline queries

Cause: The model name, view name, or field names in your query do not match what exists in Looker. Looker model names are defined in LookML and are case-sensitive.

Solution: In Looker, navigate to the Explore you want to query. The URL shows the model and explore names: /explore/{model}/{explore}. Field names use the format {view_name}.{field_name}. Use the Looker API Explorer (in Admin β†’ API Explorer) to test query construction interactively.

typescript
1// List available explores for a model to find correct names
2const explores = await lookerRequest('GET', '/lookml_models/YOUR_MODEL_NAME/explores');
3console.log('Available explores:', explores.map(e => e.name));

Looker queries time out or take very long to return

Cause: Complex Looker queries against large datasets can take 10-30 seconds or longer. Replit's default request timeout may be too short, or the query is genuinely slow due to large data volume.

Solution: Add async query execution: use the Looker API's /queries endpoint to create a query, then poll /query_tasks/{id}/status until complete. This avoids HTTP timeout issues. Also consider adding filters to limit the query's data scope, or use Looker's caching (results are cached by default for 1 hour).

403 error accessing a specific Explore or Look β€” 'Access denied'

Cause: The Looker user account used for API credentials does not have permission to view the model, explore, or Look being queried. Looker uses roles and model permissions to control data access.

Solution: In Looker Admin β†’ Roles, review the API user's role and its associated model sets. The model set must include the model you are trying to query. Ask your Looker Admin to add the appropriate model access to the API user's role.

Best practices

  • Store LOOKER_BASE_URL, LOOKER_CLIENT_ID, and LOOKER_CLIENT_SECRET in Replit Secrets (lock icon πŸ”’) β€” never hardcode these in source files
  • Create a dedicated Looker service account for API integrations with a scoped role that grants only the model and data access the integration requires
  • Cache Looker query results for at least the duration of Looker's own query cache (1 hour default) to avoid redundant computation on repeated requests
  • Use the Looker Python SDK's init40() with explicit credentials rather than relying on a looker.ini file, which can be accidentally committed to version control
  • Use run_inline_query for dynamic, parameterized queries and run_look for pre-defined, validated analyses that your data team has built in Looker
  • Handle Looker query timeouts gracefully β€” use asynchronous query execution for complex queries that may exceed HTTP timeout limits
  • Deploy data dashboard APIs as Autoscale for request-driven usage; use Reserved VM for scheduled report generation jobs that run on a fixed schedule
  • Validate Looker model and field names against the Looker API Explorer before hardcoding them in your Replit application β€” names are case-sensitive and change when models are renamed

Alternatives

Frequently asked questions

How do I connect Replit to Looker?

Generate API credentials in Looker (Admin β†’ Users β†’ Edit User β†’ API Keys), store the client ID and client secret in Replit Secrets (lock icon πŸ”’), and use the Looker Python SDK (pip install looker-sdk) or the REST API with axios. The SDK handles token authentication automatically when initialized with your credentials.

How do I securely store Looker API keys in Replit?

Click the lock icon (πŸ”’) in the Replit sidebar and add LOOKER_BASE_URL, LOOKER_CLIENT_ID, and LOOKER_CLIENT_SECRET as separate secrets. Reference them in Python with os.environ['LOOKER_CLIENT_ID'] and in Node.js with process.env.LOOKER_CLIENT_ID. Never paste credentials directly into source code files.

Can I embed Looker dashboards in a Replit-hosted application?

Yes. Use the Looker Signed Embed URL feature: your Replit server generates a signed URL using the Looker embed secret and user attributes, returns it to your frontend, and the frontend renders it in an iframe. The embed secret is stored in Replit Secrets. This gives users access to interactive Looker dashboards within your application without direct Looker accounts.

Does Replit work with both Looker Cloud and Looker self-hosted?

Yes. The Looker API is the same whether your instance is Google Cloud Looker (hosted by Google) or self-hosted. The only difference is the base URL β€” for self-hosted instances, ensure Replit can reach your Looker server's URL (it must be publicly accessible or accessible from Replit's server IPs).

What deployment type should I use for a Looker integration on Replit?

Use Autoscale for dashboard APIs that serve data to users on demand β€” queries are stateless and scale-to-zero works well. Use Reserved VM for scheduled reporting jobs that run at fixed times (daily, weekly) to ensure the service is running at the scheduled time without cold start delays.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation β€” no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.