Features Full Page Screenshot Wait for Selector & Delay Block Cookie Banners Custom Viewport & Device Website to PDF HTML to Image Dark Mode Image Format & Quality MCP Server Webhook Pricing Docs Blog Log In Sign Up

Browser Emulation

The API runs a real Chromium browser to capture screenshots. Browser emulation lets you control how that browser behaves — what it looks like to the website, where it appears to be located, and what preferences it reports. This is useful for capturing dark mode versions, bypassing bot detection, or screenshotting geo-restricted content.

Dark mode

Many websites offer a dark theme that activates based on the user's system preference. The dark_mode parameter tells the browser to report that it prefers dark colors.

ParameterTypeDefaultDescription
dark_modebooleanfalseEmulate prefers-color-scheme: dark.

This only works for websites that implement dark mode through the CSS prefers-color-scheme media query. Sites that toggle dark mode through JavaScript or cookies may need a different approach — see CSS & JS Injection for setting cookies or injecting theme-switching scripts.

Example: Dark mode screenshot

JavaScript
const response = await fetch('https://api.screenshotrun.com/v1/screenshots', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com',
    dark_mode: true,
    format: 'webp',
  }),
});

const { data } = await response.json();
console.log(data.links.image);
Python
import requests

response = requests.post(
    "https://api.screenshotrun.com/v1/screenshots",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "url": "https://example.com",
        "dark_mode": True,
        "format": "webp",
    },
)

data = response.json()["data"]
print(data["links"]["image"])
PHP
$response = Http::withToken('YOUR_API_KEY')
    ->post('https://api.screenshotrun.com/v1/screenshots', [
        'url' => 'https://example.com',
        'dark_mode' => true,
        'format' => 'webp',
    ]);

$data = $response->json('data');
cURL
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "dark_mode": true,
    "format": "webp"
  }'
Ruby
require "net/http"
require "json"

uri = URI("https://api.screenshotrun.com/v1/screenshots")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"
request["Content-Type"] = "application/json"
request.body = {
  url: "https://example.com",
  dark_mode: true,
  format: "webp",
}.to_json

response = http.request(request)
data = JSON.parse(response.body)["data"]
Go
body, _ := json.Marshal(map[string]any{
        "url": "https://example.com",
        "dark_mode": true,
        "format": "webp",
    })

req, _ := http.NewRequest("POST",
    "https://api.screenshotrun.com/v1/screenshots",
    bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

var result map[string]any
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result["data"])
Java
var client = HttpClient.newHttpClient();

var body = """
    {
        "url": "https://example.com",
        "dark_mode": true,
        "format": "webp"
    }
    """;

var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.screenshotrun.com/v1/screenshots"))
    .header("Authorization", "Bearer YOUR_API_KEY")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

var response = client.send(
    request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

Reduced motion

CSS animations can cause screenshots to capture mid-transition — elements half-faded, progress bars mid-fill, carousels between slides. The reduced_motion parameter tells the browser to prefer reduced motion, which disables CSS animations and transitions on sites that respect this preference.

ParameterTypeDefaultDescription
reduced_motionbooleanfalseEmulate prefers-reduced-motion: reduce.

Example: Static screenshot without animations

bash
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "reduced_motion": true
  }'
Tip

Not all sites respect prefers-reduced-motion. For sites that don't, you can force-disable animations with CSS injection: "css": "*, *::before, *::after { animation: none !important; transition: none !important; }"

Custom User-Agent

Some websites serve different content based on the User-Agent string — a mobile browser gets a different layout, Googlebot gets a different version, and some sites block unrecognized user agents entirely.

ParameterTypeDefaultDescription
user_agentstring—Custom User-Agent string. Overrides device preset UA. Max 500 characters.

Example: See the page as Googlebot

bash
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "user_agent": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
  }'

Stealth mode

Some websites detect headless browsers (Puppeteer, Playwright) and block them or show CAPTCHAs. They check for automation signals like the navigator.webdriver flag, missing browser plugins, or inconsistent WebGL vendor strings.

ParameterTypeDefaultDescription
stealthbooleanfalseHide browser automation signals to bypass bot detection.

Stealth mode patches the browser to look like a regular user's Chrome: it hides the WebDriver flag, reports normal plugin counts, and provides consistent WebGL vendor information. Use it when a site returns blank pages, CAPTCHAs, or "Access Denied" errors.

Example: Capture a bot-protected site

bash
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://protected-site.com",
    "stealth": true,
    "delay": 2
  }'

Timezone

Pages that display times, dates, or schedules use the browser's timezone to format them. By default, the browser uses the server's timezone. The timezone parameter lets you see the page as it would appear for a user in any timezone.

ParameterTypeDefaultDescription
timezonestring—IANA timezone (e.g. America/New_York, Europe/Berlin, Asia/Tokyo).

This affects JavaScript's Date object and the Intl formatting API. Dashboards, calendars, event listings, and news feeds will display times in the specified timezone.

Example: Dashboard in Tokyo time

bash
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/dashboard",
    "timezone": "Asia/Tokyo"
  }'

Geolocation

The geolocation parameter emulates GPS coordinates in the browser. When a page calls navigator.geolocation, it receives the coordinates you specify. This is useful for capturing maps, local search results, and location-aware content.

ParameterTypeDescription
geolocationobjectObject with latitude (-90 to 90), longitude (-180 to 180), and optional accuracy in meters. Business plan only.
Browser emulation, not IP geolocation

The geolocation parameter only affects what the browser reports via the JavaScript Geolocation API. It does not change the IP address of the request — the website will still see the server's IP address. For sites that use IP-based geo-detection (most do), combine geolocation with a proxy in the target region for full geo-spoofing.

Example: Google Maps centered on Paris

bash
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://maps.google.com",
    "geolocation": {
      "latitude": 48.8566,
      "longitude": 2.3522,
      "accuracy": 100
    }
  }'

Proxy

The proxy parameter routes all browser traffic through a proxy server you provide. The website sees the proxy's IP address instead of the API server's IP. This is essential for capturing geo-restricted content, bypassing IP-based blocks, or seeing regional pricing pages.

ParameterTypeDescription
proxystringHTTP or SOCKS5 proxy URL. Format: http://user:pass@host:port. Business plan only. Max 2,048 characters.
Bring your own proxy

ScreenshotRun does not provide built-in proxies. You need a proxy from an external provider such as Bright Data, Decodo, or Geonode. Both HTTP and SOCKS5 proxies are supported.

Each proxy request launches a dedicated browser instance — no sessions are shared between requests.

Example: Capture through a proxy

bash
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "proxy": "http://user:[email protected]:8080"
  }'

Combining emulation parameters

Dark mode dashboard in Tokyo

bash
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/dashboard",
    "dark_mode": true,
    "timezone": "Asia/Tokyo",
    "full_page": true,
    "format": "webp"
  }'

Geo-restricted content with full spoofing

Combine proxy (for IP-based detection), geolocation (for browser API), and timezone (for date formatting) to fully emulate a user in a specific location.

bash
curl -X POST https://api.screenshotrun.com/v1/screenshots \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "proxy": "http://user:[email protected]:8080",
    "geolocation": {
      "latitude": 40.7128,
      "longitude": -74.0060
    },
    "timezone": "America/New_York",
    "stealth": true
  }'