Metabase is a fantastic business intelligence tool. However, one of the things that I've run into when implementing it at different places is the fact that there's no way to programatically extract a screen cap of a question created in metabase.
You can get at the raw data, even metadata about the question. But Metabase itself won't just generate a visualization for you that you can throw into other tools. That changes today.
Metashot is a TypeScript REST API service that generates PNG images from Metabase questions using Playwright. It automatically generates secure embed URLs using JWT tokens, captures screenshots of the visualizations, uploads them to S3-compatible storage, and returns presigned download URLs. This makes it suitable to integrate with tools that need to ask for a fully realized image given a Metabase question ID.
- Generate PNG screenshots from Metabase questions using question IDs
- Automatic JWT-based embed URL generation for secure access
- Upload images to S3-compatible storage
- Return presigned URLs with configurable expiration
- Configurable viewport dimensions
- Bearer token authentication support
- Health check endpoint
- Install dependencies:
- Start local dependencies:
- Copy environment configuration:
- Run the application:
Returns API information.
Response:
Generate a screenshot from a Metabase question.
Authentication: If AUTH_TOKEN is configured, requests must include:
Request Body:
Parameters:
- questionId (required): The ID of the Metabase question to screenshot
- width (optional): Viewport width in pixels (default: 1920)
- height (optional): Viewport height in pixels (default: 1080)
Response:
Health check endpoint (no authentication required).
Response:
- npm run dev - Start development server
- npm run build - Build for production
- npm run test - Run tests
- npm run lint - Run linting
- npm run typecheck - Run TypeScript type checking
A Docker container is available for easy deployment:
A Helm chart is provided for Kubernetes deployment:
The Helm chart supports:
- External secret references for sensitive environment variables
- Ingress configuration
- Horizontal Pod Autoscaling
- Custom resource limits and requests
- Extra Kubernetes objects deployment
The docker-compose.yml provides:
- MinIO (S3-compatible storage) on port 9000
- Metabase for testing embed URLs on port 3000
Metashot integrates directly with Metabase's embedding feature:
- Prerequisites: The Metabase question must be shared via public embedding (in Metabase, go to the question > sharing icon > "Embed this question in an application")
- You provide a Metabase question ID
- Metashot generates a secure JWT token using your METABASE_SECRET_KEY
- It creates an embed URL for the question with appropriate parameters
- Playwright navigates to the embed URL and waits for the visualization to load
- A full-page screenshot is captured in PNG format
- The image is uploaded to S3-compatible storage
- A presigned URL is returned for temporary access to the image
The generated embed URLs include:
- JWT token with configurable expiry (default: 10 minutes)
- Bordered and titled display (configurable in future versions)
- Support for passing additional parameters to Metabase questions
Environment variables:
- PORT - Server port (default: 8080)
- NODE_ENV - Environment (development/production)
- AUTH_TOKEN - Bearer token required for API authentication (optional)
- METABASE_SITE_URL - Base URL of your Metabase instance (e.g., https://metabase.example.com)
- METABASE_SECRET_KEY - Secret key for generating Metabase embed tokens (found in Metabase Admin > Settings > Embedding)
- S3_ENDPOINT - S3 endpoint URL (optional, defaults to AWS S3; set for MinIO or other S3-compatible services)
- S3_ACCESS_KEY_ID - S3 access key
- S3_SECRET_ACCESS_KEY - S3 secret key
- S3_BUCKET - S3 bucket name
- S3_REGION - S3 region
- PRESIGNED_URL_EXPIRY - Presigned URL expiry in seconds (default: 3600, 1 hour)
.png)


