Docker Browser is a powerful REST API for taking screenshots, generating Lighthouse reports, and performing web analysis with extensive configuration options.
- 📸 Screenshots with customizable viewport, format, and quality
- 📊 Lighthouse Reports for performance, accessibility, SEO, and more
- 🌐 Browser Context configuration (user agent, locale, timezone, geolocation)
- 🎨 Theme Support (light/dark mode)
- ⚡ Performance optimized with Playwright and Chromium
- 🔧 Highly Configurable with comprehensive API options
Add Docker Browser to your docker-compose.yml
:
services:
appwrite-browser:
image: appwrite/browser:0.1.0
ports:
- "3000:3000"
Start the service:
docker compose up -d
Take a simple screenshot:
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
GET /v1/health
Check if the browser service is running.
curl http://localhost:3000/v1/health
Response:
{
"status": "ok"
}
GET /v1/test
Display current browser configuration values. This endpoint returns an HTML page showing what the browser currently has set, using inline JavaScript to detect and display all browser capabilities and settings. Perfect for taking screenshots to verify browser state.
curl http://localhost:3000/v1/test
The test endpoint returns an HTML page with a comprehensive visual display of current browser configuration values. The page includes:
- Viewport & Display: Screen dimensions, device pixel ratio
- Theme & Appearance: Color scheme detection
- Localization: Language, timezone settings
- Device & Hardware: Touch support, mobile detection
- User Agent: Current user agent string
- Geolocation: GPS coordinates and accuracy (if available)
- Permissions: Browser permission states
- Page Information: URL, title, ready state
The HTML page automatically adapts to the browser's theme preference (light/dark) and uses inline JavaScript to display real-time browser values.
- Browser State Inspection: See what the browser currently has configured
- Visual Verification: Take screenshots to verify browser capabilities
- Debugging: Visual inspection of browser configuration issues
- Documentation: Generate visual examples of browser behavior
- Screenshot Testing: Perfect for testing the screenshot API itself
- Development: Quick way to check browser state during development
POST /v1/screenshots
Take screenshots of web pages with extensive configuration options.
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": {
"width": 1920,
"height": 1080
},
"format": "jpeg",
"quality": 95,
"fullPage": true,
"theme": "dark",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"locale": "en-US",
"timezoneId": "America/New_York",
"geolocation": {
"latitude": 40.7128,
"longitude": -74.0060,
"accuracy": 100
},
"headers": {
"Authorization": "Bearer your-token",
"X-Custom-Header": "value"
},
"waitUntil": "networkidle",
"timeout": 60000,
"sleep": 5000,
"deviceScaleFactor": 2,
"hasTouch": true,
"isMobile": false
}'
Parameter | Type | Default | Description |
---|---|---|---|
url |
string | required | The URL to screenshot |
viewport |
object | {width: 1280, height: 720} |
Viewport dimensions |
viewport.width |
number | 1280 | Viewport width (1-3840) |
viewport.height |
number | 720 | Viewport height (1-2160) |
format |
string | "png" | Image format: "png", "jpeg", "webp" |
quality |
number | 90 | Image quality 0-100 (for jpeg/webp) |
fullPage |
boolean | false | Capture full page scroll |
clip |
object | - | Crop area: {x, y, width, height} |
theme |
string | "light" | Browser theme: "light", "dark" |
userAgent |
string | - | Custom user agent string |
locale |
string | - | Browser locale (e.g., "en-US") |
timezoneId |
string | - | IANA timezone identifier (see Timezone section) |
geolocation |
object | - | GPS coordinates |
geolocation.latitude |
number | - | Latitude (-90 to 90) |
geolocation.longitude |
number | - | Longitude (-180 to 180) |
geolocation.accuracy |
number | - | Accuracy in meters |
permissions |
array | - | Browser permissions (see Permissions section) |
headers |
object | - | Custom HTTP headers |
waitUntil |
string | " 8000 domcontentloaded" | Wait condition: "load", "domcontentloaded", "networkidle", "commit" |
timeout |
number | 30000 | Navigation timeout (0-120000ms) |
sleep |
number | 3000 | Wait time after load (0-60000ms) |
deviceScaleFactor |
number | 1 | Device pixel ratio (0.1-3) |
hasTouch |
boolean | false | Touch support |
isMobile |
boolean | false | Mobile device emulation |
POST /v1/reports
Generate Lighthouse performance, accessibility, SEO, and PWA reports.
curl -X POST http://localhost:3000/v1/reports \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
curl -X POST http://localhost:3000/v1/reports \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": "desktop",
"json": true,
"html": true,
"csv": false,
"theme": "dark",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"locale": "en-US",
"timezoneId": "America/New_York",
"headers": {
"Authorization": "Bearer your-token"
},
"thresholds": {
"performance": 90,
"accessibility": 95,
"best-practices": 85,
"seo": 80,
"pwa": 70
},
"waitUntil": "networkidle",
"timeout": 60000
}'
Parameter | Type | Default | Description |
---|---|---|---|
url |
string | required | The URL to analyze |
viewport |
string | "mobile" | Device type: "mobile", "desktop" |
json |
boolean | true | Include JSON report |
html |
boolean | false | Include HTML report |
csv |
boolean | false | Include CSV report |
theme |
string | "light" | Browser theme: "light", "dark" |
userAgent |
string | - | Custom user agent string |
locale |
string | - | Browser locale |
timezoneId |
string | - | IANA timezone identifier (see Timezone section) |
permissions |
array | - | Browser permissions (see Permissions section) |
headers |
object | - | Custom HTTP headers |
thresholds |
object | - | Performance thresholds (0-100) |
thresholds.performance |
number | 0 | Performance score threshold |
thresholds.accessibility |
number | 0 | Accessibility score threshold |
thresholds.best-practices |
number | 0 | Best practices score threshold |
thresholds.seo |
number | 0 | SEO score threshold |
thresholds.pwa |
number | 0 | PWA score threshold |
waitUntil |
string | "domcontentloaded" | Wait condition |
timeout |
number | 30000 | Navigation timeout (0-120000ms) |
The timezoneId
parameter allows you to set the browser's timezone for accurate time-based testing and content capture. This is particularly useful for testing applications that display time-sensitive content or have timezone-dependent features.
The timezoneId
must be a valid IANA timezone identifier in the format Region/City
. This is the same format used by JavaScript's Intl.DateTimeFormat
and is the standard for timezone identification.
America/New_York
- Eastern Time (US)America/Chicago
- Central Time (US)America/Denver
- Mountain Time (US)America/Los_Angeles
- Pacific Time (US)America/Toronto
- Eastern Time (Canada)America/Vancouver
- Pacific Time (Canada)America/Sao_Paulo
- Brasília Time (Brazil)America/Mexico_City
- Central Time (Mexico)America/Argentina/Buenos_Aires
- Argentina Time
Europe/London
- Greenwich Mean Time / British Summer TimeEurope/Paris
- Central European TimeEurope/Berlin
- Central European TimeEurope/Rome
- Central European TimeEurope/Madrid
- Central European TimeEurope/Amsterdam
- Central European TimeEurope/Moscow
- Moscow TimeEurope/Istanbul
- Turkey Time
Asia/Tokyo
- Japan Standard TimeAsia/Shanghai
- China Standard TimeAsia/Hong_Kong
- Hong Kong TimeAsia/Singapore
- Singapore TimeAsia/Seoul
- Korea Standard TimeAsia/Dubai
- Gulf Standard TimeAsia/Kolkata
- India Standard TimeAsia/Bangkok
- Indochina Time
Australia/Sydney
- Australian Eastern TimeAustralia/Melbourne
- Australian Eastern TimeAustralia/Perth
- Australian Western TimePacific/Auckland
- New Zealand TimePacific/Honolulu
- Hawaii-Aleutian TimePacific/Fiji
- Fiji Time
Africa/Cairo
- Eastern European TimeAfrica/Johannesburg
- South Africa Standard TimeAfrica/Lagos
- West Africa TimeAfrica/Nairobi
- East Africa Time
UTC
- Coordinated Universal TimeGMT
- Greenwich Mean Time
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"timezoneId": "America/New_York"
}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://ecommerce-site.com",
"timezoneId": "Asia/Tokyo",
"locale": "ja-JP"
}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://api-dashboard.com",
"timezoneId": "UTC"
}'
Here's a complete test command that showcases all available parameters:
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": {
"width": 1920,
"height": 1080
},
"format": "jpeg",
"quality": 95,
"fullPage": true,
"theme": "dark",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"locale": "en-US",
"timezoneId": "America/New_York",
"geolocation": {
"latitude": 40.7128,
"longitude": -74.0060,
"accuracy": 100
},
"permissions": [
"geolocation",
"notifications",
"camera",
"microphone",
"clipboard-read",
"clipboard-write"
],
"headers": {
"Authorization": "Bearer test-token-12345",
"X-Custom-Header": "test-value",
"X-Request-ID": "screenshot-test-001"
},
"waitUntil": "networkidle",
"timeout": 60000,
"sleep": 5000,
"deviceScaleFactor": 2,
"hasTouch": true,
"isMobile": false
}' \
--output "comprehensive-test-screenshot.jpg"
Mobile Device Test Command
8000 div>curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": {
"width": 375,
"height": 667
},
"format": "png",
"quality": 90,
"fullPage": true,
"theme": "light",
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",
"locale": "en-US",
"timezoneId": "America/Los_Angeles",
"geolocation": {
"latitude": 37.7749,
"longitude": -122.4194,
"accuracy": 50
},
"permissions": [
"geolocation",
"camera",
"microphone",
"notifications"
],
"headers": {
"X-Mobile-App": "true",
"X-Device-Type": "mobile"
},
"waitUntil": "domcontentloaded",
"timeout": 30000,
"sleep": 3000,
"deviceScaleFactor": 3,
"hasTouch": true,
"isMobile": true
}' \
--output "mobile-test-screenshot.png"
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": {
"width": 2560,
"height": 1440
},
"format": "jpeg",
"quality": 100,
"fullPage": true,
"theme": "dark",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"locale": "en-US",
"timezoneId": "Europe/London",
"geolocation": {
"latitude": 51.5074,
"longitude": -0.1278,
"accuracy": 20
},
"permissions": [
"geolocation",
"notifications",
"camera",
"microphone",
"clipboard-read",
"clipboard-write",
"payment-handler",
"usb",
"bluetooth"
],
"headers": {
"Authorization": "Bearer premium-token",
"X-Premium-User": "true",
"X-Request-Source": "screenshot-api"
},
"waitUntil": "networkidle",
"timeout": 90000,
"sleep": 8000,
"deviceScaleFactor": 2,
"hasTouch": false,
"isMobile": false
}' \
--output "high-quality-desktop-screenshot.jpg"
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": {
"width": 1920,
"height": 1080
},
"format": "png",
"quality": 90,
"fullPage": false,
"clip": {
"x": 100,
"y": 100,
"width": 800,
"height": 600
},
"theme": "light",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0",
"locale": "en-GB",
"timezoneId": "Europe/Berlin",
"permissions": [
"geolocation",
"notifications"
],
"headers": {
"X-Test-Mode": "clipped-screenshot",
"X-Region": "europe"
},
"waitUntil": "load",
"timeout": 45000,
"sleep": 2000,
"deviceScaleFactor": 1.5,
"hasTouch": false,
"isMobile": false
}' \
--output "clipped-screenshot.png"
- E-commerce: Test pricing displays in different timezones
- Scheduling Apps: Verify appointment times across regions
- News Sites: Check time-sensitive content display
- Financial Apps: Test market hours and trading times
- Social Media: Verify post timestamps and feeds
- Analytics: Test time-based reporting accuracy
The API validates timezone identifiers using the IANA timezone database format. Invalid timezone identifiers will result in a validation error with a helpful message.
Valid format: Region/City
(e.g., America/New_York
)
Invalid formats:
EST
,PST
(abbreviations not supported)UTC+5
(offset format not supported)New York
(missing region prefix)
The permissions
parameter allows you to grant specific browser permissions to the page during screenshot capture or report generation. This is useful for testing features that require user permission or for capturing content that depends on specific browser capabilities.
Permission | Description | Use Case |
---|---|---|
geolocation |
Access to device location | Location-based features, maps |
camera |
Access to device camera | Video calls, photo capture |
microphone |
Access to device microphone | Audio recording, voice calls |
notifications |
Display notifications | Push notifications, alerts |
clipboard-read |
Read from clipboard | Copy/paste functionality |
clipboard-write |
Write to clipboard | Copy/paste functionality |
payment-handler |
Handle payment requests | E-commerce, payment flows |
midi |
Access to MIDI devices | Music applications |
usb |
Access to USB devices | Hardware integration |
serial |
Access to serial ports | Hardware communication |
bluetooth |
Access to Bluetooth devices | IoT, wireless devices |
persistent-storage |
Persistent storage access | Offline data storage |
accelerometer |
Access to accelerometer | Motion detection, games |
gyroscope |
Access to gyroscope | Orientation, VR/AR |
magnetometer |
Access to magnetometer | Compass, navigation |
ambient-light-sensor |
Access to light sensor | Auto-brightness, themes |
background-sync |
Background synchronization | Offline sync |
background-fetch |
Background data fetching | Offline content |
idle-detection |
Detect user idle state | Power management |
periodic-background-sync |
Periodic background sync | Scheduled updates |
push |
Push messaging | Real-time notifications |
speaker-selection |
Audio output selection | Audio routing |
storage-access |
Cross-site storage access | Third-party cookies |
top-level-storage-access |
Top-level storage access | First-party storage |
window-management |
Window management | Multi-window apps |
local-fonts |
Access to local fonts | Custom typography |
display-capture |
Screen capture | Screen sharing |
nfc |
Near Field Communication | Contactless payments |
screen-wake-lock |
Prevent screen sleep | Always-on displays |
web-share |
Web Share API | Native sharing |
xr-spatial-tracking |
XR spatial tracking | VR/AR applications |
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"permissions": ["geolocation", "notifications"]
}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://video-call-app.com",
"permissions": ["camera", "microphone", "notifications"]
}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://iot-dashboard.com",
"permissions": ["usb", "bluetooth", "serial"]
}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://vr-app.com",
"permissions": ["xr-spatial-tracking", "accelerometer", "gyroscope", "magnetometer"]
}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://ecommerce-site.com",
"permissions": ["payment-handler", "clipboard-write", "nfc"]
}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": {"width": 375, "height": 667},
"isMobile": true,
"hasTouch": true,
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)"
}'
High-Quality Screenshot
< 9A15 svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true">curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "jpeg",
"quality": 100,
"deviceScaleFactor": 2,
"fullPage": true
}'
curl -X POST http://localhost:3000/v1/screenshots \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"geolocation": {
"latitude": 37.7749,
"longitude": -122.4194,
"accuracy": 100
},
"timezoneId": "America/Los_Angeles"
}'
curl -X POST http://localhost:3000/v1/reports \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": "desktop",
"thresholds": {
"performance": 90,
"accessibility": 95,
"best-practices": 85,
"seo": 80
},
"html": true
}'
Make sure you have pnpm installed.
Install dependencies:
pnpm i
Start the development server:
npm start
The API will be available at http://localhost:3000
.
All code contributions, including those of people having commit access, must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code.
We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the contribution guide.