Nodium Screenshot API -- API Reference
Complete reference for all endpoints, parameters, error codes, and response headers.
Base URL: https://api.nodium.io/api/v1/screenshot
Table of Contents
- 1. Source - 2. Format & Response - 3. Viewport & Devices - 4. Full Page - 5. Selector - 6. Clip (Crop) - 7. Blocking - 8. Customization (CSS/JS Injection) - 9. Display Emulation - 10. Wait & Timing - 11. Request (Headers, Auth, Cookies) - 12. Geolocation - 13. Proxy - 14. Image Post-Processing - 15. PDF - 16. Cache - 17. Async & Webhooks - 18. Metadata Extraction - 19. Error Control - 20. Security -- Signed URLs - 21. AI Vision (OpenAI) - 22. Effects
Endpoints
GET/POST /take -- Static Screenshot
Captures a static screenshot of a web page, raw HTML, or Markdown content.
GET https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png
POST https://api.nodium.io/api/v1/screenshot/take
- GET: Parameters passed as query string
- POST: Parameters passed as JSON body (Content-Type:
application/json), or as query string, or mixed
Returns the screenshot as binary data (default), JSON metadata, or empty response depending on response_type.
GET/POST /animate -- Animated Screenshot / Video
Records a video or animated GIF of a web page, including scroll animations.
GET https://api.nodium.io/api/v1/screenshot/animate?access_key=KEY&url=https://example.com&format=mp4
POST https://api.nodium.io/api/v1/screenshot/animate
Supports all /take parameters plus animation-specific parameters.
POST /bulk -- Batch Screenshots
Captures multiple screenshots in a single request.
POST https://api.nodium.io/api/v1/screenshot/bulk
See Bulk Parameters for request format.
GET /usage -- Usage Statistics
Returns current usage and quota information.
GET https://api.nodium.io/api/v1/screenshot/usage?access_key=KEY
Response:
json
{
"total": 10000,
"available": 7523,
"used": 2477,
"concurrency": {
"limit": 10,
"remaining": 8,
"reset": 1709654400000000000
}
}
| Field | Type | Description |
|---|
total | integer | Total screenshots allowed in the current billing period |
available | integer | Screenshots remaining |
used | integer | Screenshots successfully consumed |
concurrency.limit | integer | Maximum concurrent requests |
concurrency.remaining | integer | Concurrent request slots available right now |
concurrency.reset | integer | Reset timestamp (UNIX nanoseconds) |
Parameters
1. Source
One (and only one) source parameter is required per request.
| Parameter | Type | Default | Description | Example |
|---|
url | string | -- | URL of the web page to capture. Must be a valid HTTP/HTTPS URL. | https://example.com |
html | string | -- | Raw HTML content to render and capture. | <h1>Hello World</h1> |
markdown | string | -- | Markdown content to render and capture. Converted to HTML before rendering. | # Hello World |
bash
# Capture a URL
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png" -o page.png
# Render HTML
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{"html": "<h1 style=\"color:blue\">Hello Nodium</h1>", "format": "png"}' \
-o html.png
# Render Markdown
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{"markdown": "# Hello Nodium\n\nThis is **bold** text.", "format": "png"}' \
-o md.png
2. Format & Response
| Parameter | Type | Default | Description | Example |
|---|
format | string | png | Output format. Image: png, jpeg/jpg, webp, avif, heif, tiff, jp2, gif. Document: pdf, html, markdown. | webp |
response_type | string | by_format | How the response is returned. by_format = raw binary, json = JSON metadata with screenshot URL, empty = HTTP status only. | json |
bash
# Get JSON response with metadata
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&response_type=json"
3. Viewport & Devices
| Parameter | Type | Default | Description | Example |
|---|
viewport_width | integer | 1280 | Viewport width in pixels. | 1440 |
viewport_height | integer | 1024 | Viewport height in pixels. | 900 |
device_scale_factor | float | 1 | Device pixel ratio (1--5, supports decimals like 2.25). Set to 2 for Retina displays. | 2 |
viewport_device | string | -- | Preset device ID. Automatically sets width, height, scale factor, mobile, touch, landscape, and user agent. Individual parameters can override the preset. See Device Presets. | iphone_16_pro |
viewport_mobile | boolean | false | Enable mobile viewport meta tag handling. | true |
viewport_has_touch | boolean | false | Enable touch event emulation. | true |
viewport_landscape | boolean | false | Rotate the viewport to landscape orientation. | true |
bash
# Retina screenshot
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&device_scale_factor=2" -o retina.png
# iPhone 16 Pro emulation
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&viewport_device=iphone_16_pro" -o iphone.png
# Custom dimensions, landscape
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&viewport_width=1920&viewport_height=1080&viewport_landscape=true" -o wide.png
Device Presets
The viewport_device parameter accepts any of the following preset IDs. Each portrait device also has a _landscape variant (e.g. iphone_16_landscape).
Apple -- iPhones
| Device ID | Width | Height | Scale |
|---|
iphone_se | 375 | 667 | 2 |
iphone_xr | 414 | 896 | 2 |
iphone_11 | 414 | 896 | 2 |
iphone_11_pro | 375 | 812 | 3 |
iphone_11_pro_max | 414 | 896 | 3 |
iphone_12_mini | 375 | 812 | 3 |
iphone_12 | 390 | 844 | 3 |
iphone_12_pro | 390 | 844 | 3 |
iphone_13_mini | 375 | 812 | 3 |
iphone_13 | 390 | 844 | 3 |
iphone_13_pro | 390 | 844 | 3 |
iphone_13_pro_max | 428 | 926 | 3 |
iphone_14 | 390 | 844 | 3 |
iphone_14_pro | 393 | 852 | 3 |
iphone_14_pro_max | 430 | 932 | 3 |
iphone_15 | 393 | 852 | 3 |
iphone_15_pro | 393 | 852 | 3 |
iphone_15_pro_max | 430 | 932 | 3 |
iphone_16 | 393 | 852 | 3 |
iphone_16_pro | 402 | 874 | 3 |
iphone_16_pro_max | 440 | 956 | 3 |
Apple -- iPads
| Device ID | Width | Height | Scale |
|---|
ipad | 810 | 1080 | 2 |
ipad_air | 820 | 1180 | 2 |
ipad_mini | 744 | 1133 | 2 |
ipad_pro_11 | 834 | 1194 | 2 |
ipad_pro_12_9 | 1024 | 1366 | 2 |
Google Pixel
| Device ID | Width | Height | Scale |
|---|
pixel_5 | 393 | 851 | 2.75 |
pixel_6 | 412 | 915 | 2.625 |
pixel_7 | 412 | 915 | 2.625 |
pixel_7_pro | 412 | 892 | 2.625 |
pixel_8 | 412 | 915 | 2.625 |
pixel_8_pro | 412 | 892 | 2.625 |
pixel_9 | 412 | 915 | 2.625 |
pixel_9_pro | 412 | 892 | 2.625 |
pixel_9_pro_fold | 373 | 839 | 2.625 |
Samsung Galaxy
| Device ID | Width | Height | Scale |
|---|
galaxy_s21 | 360 | 800 | 3 |
galaxy_s22 | 360 | 780 | 3 |
galaxy_s23 | 360 | 780 | 3 |
galaxy_s24 | 360 | 780 | 3 |
galaxy_s24_ultra | 384 | 824 | 3 |
galaxy_note_20 | 412 | 883 | 3 |
galaxy_z_fold_5 | 373 | 839 | 3 |
galaxy_z_flip_5 | 360 | 780 | 3 |
galaxy_a54 | 412 | 915 | 2.625 |
galaxy_tab_s9 | 800 | 1280 | 2 |
galaxy_tab_s9_ultra | 1024 | 1366 | 2 |
Other Android
| Device ID | Width | Height | Scale |
|---|
oneplus_12 | 412 | 915 | 3.5 |
xiaomi_14 | 393 | 873 | 3 |
kindle_fire_hdx | 800 | 1280 | 2 |
Microsoft Surface
| Device ID | Width | Height | Scale |
|---|
surface_pro_9 | 1368 | 912 | 2 |
surface_duo | 540 | 720 | 2.5 |
Desktop
| Device ID | Width | Height | Scale |
|---|
desktop_hd | 1280 | 720 | 1 |
desktop_wxga | 1280 | 800 | 1 |
desktop_sxga | 1280 | 1024 | 1 |
desktop_1080p | 1920 | 1080 | 1 |
desktop_uxga | 1600 | 1200 | 1 |
desktop_wuxga | 1920 | 1200 | 1 |
desktop_1440p | 2560 | 1440 | 1 |
desktop_4k | 3840 | 2160 | 1 |
Laptops / Macs
| Device ID | Width | Height | Scale |
|---|
laptop | 1366 | 768 | 1 |
macbook_air | 1440 | 900 | 2 |
macbook_air_15 | 1710 | 1112 | 2 |
macbook_pro_14 | 3024 | 1964 | 2 |
macbook_pro_16 | 3456 | 2234 | 2 |
imac_24 | 4480 | 2520 | 2 |
Social Media
| Device ID | Width | Height | Use Case |
|---|
social_instagram_post | 1080 | 1080 | Instagram square post |
social_instagram_story | 1080 | 1920 | Instagram story / Reels |
social_twitter_post | 1200 | 675 | Twitter/X card |
social_facebook_post | 1200 | 630 | Facebook link preview |
social_linkedin_post | 1200 | 627 | LinkedIn post image |
social_og_image | 1200 | 630 | Open Graph image |
4. Full Page
| Parameter | Type | Default | Description | Example |
|---|
full_page | boolean | false | Capture the entire scrollable page, not just the visible viewport. | true |
full_page_scroll | boolean | true (when full_page is enabled) | Physically scroll the page before capture. Triggers lazy-loaded images and content. | true |
full_page_scroll_delay | integer (ms) | 400 | Delay between each scroll step. Increase for pages with heavy lazy-loading. | 800 |
full_page_scroll_by | integer (px) | viewport height | Pixels to scroll per step. | 500 |
full_page_max_height | integer (px) | unlimited | Maximum capture height. Protects against infinite-scroll pages. | 15000 |
full_page_algorithm | string | default | default = Chrome DevTools Protocol native capture. by_sections = captures section by section then stitches. | by_sections |
bash
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&full_page=true&full_page_scroll=true&full_page_scroll_delay=600&full_page_max_height=20000" -o fullpage.png
5. Selector
| Parameter | Type | Default | Description | Example |
|---|
selector | string (CSS) | -- | CSS selector of the element to capture. Only that element is included in the output. Prefix with shadow/ to traverse Shadow DOM (e.g. shadow/.my-element). | #main-content |
selector_algorithm | string | default | default = browser-native bounding box. clip = clip-based capture (better for partially visible elements). | clip |
selector_scroll_into_view | boolean | true | Scroll to the element before capturing. Useful for triggering lazy-load. | true |
error_on_selector_not_found | boolean | false | Return an error if the CSS selector does not match any element. | true |
scroll_into_view | string (CSS) | -- | Scroll the page until this selector is visible, then capture the full viewport. | .footer |
scroll_into_view_adjust_top | integer (px) | 0 | Vertical offset adjustment when scrolling to the element. Positive = down, negative = up. | -50 |
capture_beyond_viewport | boolean | false | Allow capturing content that extends beyond the visible viewport. | true |
bash
# Capture a specific element
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&selector=%23main-content" -o element.png
# Capture an element inside Shadow DOM
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&selector=shadow/.hero-banner" -o shadow.png
6. Clip (Crop)
Crop a rectangular region from the page. All four parameters must be provided together.
| Parameter | Type | Default | Description | Example |
|---|
clip_x | integer | -- | Left coordinate of the crop area in pixels. | 100 |
clip_y | integer | -- | Top coordinate of the crop area in pixels. | 200 |
clip_width | integer | -- | Width of the crop area in pixels. | 800 |
clip_height | integer | -- | Height of the crop area in pixels. | 600 |
bash
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&clip_x=0&clip_y=0&clip_width=800&clip_height=400" -o cropped.png
7. Blocking
| Parameter | Type | Default | Description | Example |
|---|
block_ads | boolean | false | Block advertisements using EasyList/uBlock filter lists. | true |
block_cookie_banners | boolean | false | Block GDPR/cookie consent banners. | true |
block_banners_by_heuristics | boolean | false | Alternative heuristic-based banner blocking. Use if block_cookie_banners is insufficient. | true |
block_chats | boolean | false | Block live chat widgets (Intercom, Crisp, Drift, Tawk, Zoho, FB Messenger, etc.). | true |
block_trackers | boolean | false | Block analytics and tracking scripts. | true |
block_requests | string[] | -- | Block network requests matching URL patterns. Supports wildcards (*). | ["google-analytics", ".doubleclick.net"] |
block_resources | string[] | -- | Block requests by resource type: document, stylesheet, image, media, font, script, xhr, fetch, websocket, eventsource, manifest, other. | ["font", "media"] |
hide_selectors | string[] | -- | Hide elements by CSS selector (applies display: none !important). | [".popup", "#banner"] |
bash
# Clean screenshot without distractions
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&block_ads=true&block_cookie_banners=true&block_chats=true&block_trackers=true" -o clean.png
# Block specific domains
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "png",
"block_requests": ["*analytics*", "*tracking*"],
"hide_selectors": [".newsletter-popup", ".cookie-banner"]
}' -o blocked.png
8. Customization (CSS/JS Injection)
| Parameter | Type | Default | Description | Example |
|---|
styles | string | -- | Custom CSS injected into the page before capture. | body { font-size: 18px; } .ad { display: none; } |
scripts | string | -- | Custom JavaScript executed before capture. | document.querySelector('.popup').remove(); |
scripts_wait_until | string[] | -- | Navigation events to wait for after script execution: load, domcontentloaded, networkidle0, networkidle2. Required if the script triggers a redirect. | ["networkidle0"] |
click | string (CSS) | -- | Click on an element before capture. Supports shadow/ prefix for Shadow DOM. | .accept-cookies |
error_on_click_selector_not_found | boolean | true | Return an error if the click target is not found. | false |
hover | string (CSS) | -- | Hover over an element before capture. Supports shadow/ prefix. | .tooltip-trigger |
error_on_hover_selector_not_found | boolean | true | Return an error if the hover target is not found. | false |
bash
# Inject custom styles
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&styles=body%7Bbackground%3Ared%7D" -o styled.png
# Click a button before capture
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "png",
"click": ".accept-cookies",
"delay": 1
}' -o clicked.png
9. Display Emulation
| Parameter | Type | Default | Description | Example |
|---|
dark_mode | boolean | -- | Force color scheme. true = prefers-color-scheme: dark, false = prefers-color-scheme: light. Omit to use the site default. | true |
reduced_motion | boolean | false | Force prefers-reduced-motion: reduce. Disables CSS animations. | true |
media_type | string | screen | CSS media type emulation. screen (default) or print (useful for PDF). | print |
omit_background | boolean | false | Transparent page background. Works with PNG, WebP (images) and MOV (video). | true |
bash
# Dark mode screenshot
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&dark_mode=true" -o dark.png
# Transparent background
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&omit_background=true" -o transparent.png
10. Wait & Timing
| Parameter | Type | Default | Description | Example |
|---|
delay | integer (seconds) | 0 | Additional wait time after page load, before capture. Values > 30s require async=true and timeout > 300. | 3 |
wait_until | string[] | ["load"] | Browser events to wait for: load, domcontentloaded, networkidle0 (0 connections for 500ms), networkidle2 (max 2 connections for 500ms). When multiple values are given, all must be satisfied. | ["load", "networkidle2"] |
wait_for_selector | string (CSS) | -- | Wait until this CSS selector appears in the DOM. Supports comma-separated selectors. | .content-loaded |
wait_for_selector_algorithm | string | at_least_one | at_least_one = any selector matches. at_least_by_count = each selector matches at least once. | at_least_by_count |
timeout | integer (seconds) | 60 | Global timeout. Max: 90 (sync), 300 (async). | 90 |
navigation_timeout | integer (seconds) | 30 | Navigation timeout. Max: 30. | 15 |
bash
# Wait for dynamic content
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&wait_until=networkidle0&wait_for_selector=.main-content&delay=2" -o waited.png
| Parameter | Type | Default | Description | Example |
|---|
user_agent | string | Chrome default | Custom User-Agent string. Overridden by viewport_device. | MyBot/1.0 |
headers | string[] | -- | Custom HTTP headers. Format: Header-Name:Header-Value. Multiple headers supported. | ["X-Custom:value", "Accept-Language:fr-FR"] |
cookies | string[] | -- | Custom cookies. Format: name=value; Domain=domain; Secure; HttpOnly. Multiple cookies supported. | ["session=abc123; Domain=example.com"] |
authorization | string | -- | Authorization header value. Supports Basic, Bearer, and other schemes. | Bearer eyJhbGci... |
time_zone | string | -- | Emulated timezone. Uses IANA timezone IDs. | Europe/Paris |
bypass_csp | boolean | false | Bypass the site's Content Security Policy. Necessary when injecting custom scripts on pages with strict CSP. | true |
bash
# Screenshot with authentication
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://app.example.com/dashboard",
"format": "png",
"authorization": "Bearer eyJhbGciOiJIUzI1NiIs...",
"cookies": ["session=abc123; Domain=example.com; Secure"],
"time_zone": "America/New_York"
}' -o dashboard.png
12. Geolocation
All geolocation parameters must be provided together.
| Parameter | Type | Default | Description | Example |
|---|
geolocation_latitude | float | -- | Latitude coordinate. | 48.858184 (Eiffel Tower) |
geolocation_longitude | float | -- | Longitude coordinate. | 2.294720 |
geolocation_accuracy | float (meters) | -- | Accuracy in meters. | 10 |
bash
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://maps.google.com&format=png&geolocation_latitude=48.858184&geolocation_longitude=2.294720&geolocation_accuracy=10" -o paris.png
13. Proxy
| Parameter | Type | Default | Description | Example |
|---|
ip_country_code | string | -- | Route through a datacenter proxy in the specified country. Supported: us, gb, de, fr, it, es, jp, kr, cn, in, au, br, mx, ca, nz, pe, is, ie. | us |
proxy | string | -- | Custom HTTP proxy. Format: http://user:password@host:port/. Overrides ip_country_code. | http://user:pass@proxy.example.com:8080/ |
bash
# Capture as seen from Japan
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&ip_country_code=jp" -o japan.png
14. Image Post-Processing
| Parameter | Type | Default | Description | Example |
|---|
image_quality | integer (0--100) | 80 | Image compression quality. Applies to: jpeg, webp, png, tiff, jp2, avif, heif. | 95 |
image_width | integer | viewport width | Resize the output image to this width. Aspect ratio is preserved. | 640 |
image_height | integer | viewport height | Resize the output image to this height. Aspect ratio is preserved. | 480 |
bash
# High-quality JPEG with specific dimensions
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=jpeg&image_quality=95&image_width=800" -o resized.jpg
15. PDF
| Parameter | Type | Default | Description | Example |
|---|
pdf_print_background | boolean | false | Print background graphics and colors. | true |
pdf_fit_one_page | boolean | false | Scale content to fit on a single page. | true |
pdf_landscape | boolean | false | Landscape orientation. | true |
pdf_paper_format | string | a4 | Paper size: a0, a1, a2, a3, a4, a5, a6, legal, letter, tabloid. | letter |
pdf_margin | string | 0 | Uniform margin for all sides. Accepts CSS units. | 20px |
pdf_margin_top | string | -- | Override top margin. | 10mm |
pdf_margin_right | string | -- | Override right margin. | 10mm |
pdf_margin_bottom | string | -- | Override bottom margin. | 10mm |
pdf_margin_left | string | -- | Override left margin. | 10mm |
Recommended combination for full-page PDF: format=pdf&media_type=screen&pdf_print_background=true&pdf_fit_one_page=true
bash
# Generate a PDF with background and margins
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=pdf&pdf_print_background=true&pdf_paper_format=a4&pdf_margin=20px" -o document.pdf
16. Cache
| Parameter | Type | Default | Description | Example |
|---|
cache | boolean | false | Enable caching. Cached screenshots are not counted against your quota and are not logged. | true |
cache_ttl | integer (seconds) | -- | Cache time-to-live. Min: 14400 (4 hours), Max: 2592000 (30 days). | 86400 (24 hours) |
cache_key | string | -- | Custom cache key to differentiate cached versions. | homepage-v2 |
Cache behavior:
- The cache key is computed from all request parameters combined
- Cached results are served via CDN and are shareable without exposing your API key
- The cache URL is returned in the
x-nodium-cache-url response header and in the JSON response (cache_url) - Caching is not compatible with webhooks
bash
# Cache for 24 hours
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&cache=true&cache_ttl=86400" -o cached.png
17. Async & Webhooks
| Parameter | Type | Default | Description | Example |
|---|
async | boolean | false | Run the screenshot asynchronously. Returns 202 Accepted immediately after credential validation. Result is delivered via webhook. | true |
webhook_url | string | -- | URL to POST the screenshot result to when processing completes. | https://hooks.example.com/screenshot |
webhook_sign | boolean | true | Sign the webhook body with HMAC SHA-256 using your signing key. | true |
webhook_errors | boolean | false | Include error details in the webhook payload. | true |
external_identifier | string | -- | Custom identifier returned in the webhook headers as x-nodium-external-identifier. | order-12345 |
Webhook headers delivered to your endpoint:
| Header | Description |
|---|
X-Nodium-Signature | HMAC SHA-256 signature of the body |
x-nodium-rendering-seconds | Rendering time |
x-nodium-size-bytes | Screenshot file size |
x-nodium-trace-id | Trace ID |
x-nodium-reference | Screenshot reference |
x-nodium-external-identifier | Your custom identifier |
x-nodium-error-code | Error code (if webhook_errors=true) |
x-nodium-error-message | Error message (if webhook_errors=true) |
bash
# Async screenshot with webhook
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://heavy-page.example.com",
"format": "png",
"async": true,
"webhook_url": "https://hooks.example.com/screenshot-ready",
"webhook_sign": true,
"external_identifier": "job-42"
}'
All metadata parameters are disabled by default for performance. Enable only what you need.
| Parameter | Type | Default | Description | JSON Response Field | Response Header |
|---|
metadata_image_size | boolean | false | Output image dimensions. | metadata.image_size.{width, height} | x-nodium-image-width, x-nodium-image-height |
metadata_page_title | boolean | false | Page <title> tag. | metadata.page_title | x-nodium-page-title |
metadata_open_graph | boolean | false | Open Graph meta tags (title, description, image, url, type, site_name). | metadata.open_graph | x-nodium-open-graph |
metadata_icon | boolean | false | Favicon URL and type. | metadata.icon.{url, type} | x-nodium-icon |
metadata_fonts | boolean | false | Fonts used on the page. | metadata.fonts | -- |
metadata_content | boolean | false | Extract page content and upload to CDN. Returns a temporary URL. | content.{url, expires} | x-nodium-content-url, x-nodium-content-expires |
metadata_content_format | string | html | Format for content extraction: html or markdown. | -- | -- |
metadata_http_response_status_code | boolean | false | HTTP status code returned by the target site. | http_response.status_code | x-nodium-http-status-code |
metadata_http_response_headers | boolean | false | HTTP response headers from the target site. | http_response.headers | x-nodium-http-headers |
bash
# Extract Open Graph data and page title
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&response_type=json&metadata_page_title=true&metadata_open_graph=true&metadata_icon=true"
19. Error Control
| Parameter | Type | Default | Description | Example |
|---|
ignore_host_errors | boolean | false | Capture the screenshot even if the target site returns a non-2xx HTTP status code. | true |
fail_if_content_contains | string[] | -- | Fail if the page body contains any of the specified strings (case-insensitive). | ["Access Denied", "404 Not Found"] |
fail_if_content_missing | string[] | -- | Fail if the page body does not contain any of the specified strings (case-insensitive). | ["Welcome back"] |
fail_if_request_failed | string | -- | Fail if any network request matching this URL pattern fails. | api.example.com |
fail_if_gpu_rendering_fails | boolean | false | Fail instead of falling back to CPU/software rendering when GPU is unavailable. | true |
Note: Screenshots that fail due to fail_if_* conditions are not counted against your quota.
bash
# Fail if the page shows an error
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://example.com/dashboard",
"format": "png",
"fail_if_content_contains": ["Access Denied", "Login Required"],
"fail_if_content_missing": ["Dashboard"]
}' -o dashboard.png
20. Security -- Signed URLs
| Parameter | Type | Default | Description | Example |
|---|
signature | string | -- | HMAC-SHA256 signature of all request parameters, generated with your signing key. | a1b2c3d4e5f6... |
How it works:
- Concatenate all query parameters (sorted alphabetically, excluding
signature) into a canonical string - Sign the string using HMAC-SHA256 with your signing key (available in the Nodium Dashboard)
- Append the hex-encoded signature as the
signature parameter
Enforcement: Signature validation can be made mandatory for your organization in the Dashboard under Settings > Signed URLs. When enforced, all requests without a valid signature are rejected with signature_is_required.
Use case: Signed URLs allow you to safely expose screenshot URLs on the client side (e.g. in <img> tags) without revealing your API key.
bash
# Signed URL example
curl "https://api.nodium.io/api/v1/screenshot/take?access_key=KEY&url=https://example.com&format=png&signature=a1b2c3d4e5f6789012345678abcdef"
21. AI Vision (OpenAI)
| Parameter | Type | Default | Description | Example |
|---|
openai_api_key | string | -- | Your OpenAI API key. Not stored by Nodium. | sk-proj-... |
vision_prompt | string | -- | Prompt sent to GPT Vision along with the screenshot. | Describe the layout of this page |
vision_max_tokens | integer | -- | Maximum tokens for the GPT Vision response. | 500 |
The Vision completion is returned in:
- JSON response:
vision.completion - Header:
X-Nodium-Vision-Completion
bash
# Analyze a screenshot with GPT Vision
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "png",
"response_type": "json",
"openai_api_key": "sk-proj-...",
"vision_prompt": "List all navigation menu items visible on this page.",
"vision_max_tokens": 300
}'
22. Effects
| Parameter | Type | Default | Description | Example |
|---|
watermark | string | -- | Text watermark overlaid on the image. | DRAFT |
watermark_image_url | string | -- | URL of an image to use as watermark. | https://example.com/logo.png |
watermark_opacity | float (0--1) | 0.5 | Watermark opacity. | 0.3 |
blur | string[] | -- | CSS selectors of elements to blur (useful for anonymizing sensitive data). | [".email", ".phone-number"] |
bash
# Watermark and blur sensitive info
curl -X POST "https://api.nodium.io/api/v1/screenshot/take" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://example.com/profile",
"format": "png",
"watermark": "CONFIDENTIAL",
"watermark_opacity": 0.2,
"blur": [".personal-info", ".credit-card"]
}' -o redacted.png
Animation Parameters (/animate)
The /animate endpoint accepts all parameters from /take plus the following animation-specific parameters.
Core Animation
| Parameter | Type | Default | Description | Example |
|---|
scenario | string | default | Animation scenario. default = records the page after load without scrolling. scroll = records a scroll animation. | scroll |
format | string | mp4 | Video format: mp4, webm, gif, mov, avi. | gif |
duration | integer (seconds) | 5 | Recording duration. Min: 1, Max: 30. | 10 |
width | integer | viewport width | Video width. Ignored if aspect_ratio is set. | 1280 |
height | integer | viewport height | Video height. Ignored if aspect_ratio is set. | 720 |
aspect_ratio | string | -- | Aspect ratio (overrides width/height). | 16:9 |
Scroll Animation (scenario=scroll)
| Parameter | Type | Default | Description |
|---|
scroll_delay | integer (ms) | 500 | Delay between scroll steps. |
scroll_duration | integer (ms) | 1500 | Duration of a single scroll action. |
scroll_by | integer (px) | 1000 | Pixels per scroll step. |
scroll_start_immediately | boolean | true | Start scrolling immediately or wait for scroll_delay. |
scroll_start_delay | integer (ms) | 0 | Wait time before the first scroll. |
scroll_back | boolean | true | Scroll back up after reaching the bottom. |
scroll_back_algorithm | string | once | once = smooth scroll up with easing. repeat = reverse the scroll-down algorithm. |
scroll_back_after_duration | integer (ms) | -- | Start scrolling back after this duration. |
scroll_complete | boolean | true | Stop recording when the scroll completes. |
scroll_stop_after_duration | integer (ms) | -- | Stop scrolling after this duration. |
scroll_easing | string | ease_in_out_quint | Easing function (see below). |
scroll_try_navigate | boolean | -- | Navigate to a new page during the scroll. |
scroll_navigate_after | integer (ms) | duration / 2 | When to navigate during the scroll. |
scroll_navigate_to_url | string | -- | Destination URL for navigation. |
scroll_navigate_link_hints | string[] | ["pricing", "about", "customers"] | Keywords to match link text for auto-navigation. |
scroll_till_selector | string (CSS) | -- | Scroll until this selector becomes visible. |
scroll_till_selector_adjust_top | integer | -- | Vertical offset when scrolling to the selector. |
scroll_to_end_after | integer (ms) | -- | Jump to the bottom after this duration, in one smooth motion with easing. |
Easing Functions
Available values for scroll_easing:
| Function | Description |
|---|
linear | Constant speed |
ease_in_quad | Gradual acceleration (quadratic) |
ease_out_quad | Gradual deceleration (quadratic) |
ease_in_out_quad | Acceleration then deceleration (quadratic) |
ease_in_cubic | Gradual acceleration (cubic) |
ease_out_cubic | Gradual deceleration (cubic) |
ease_in_out_cubic | Acceleration then deceleration (cubic) |
ease_in_quart | Gradual acceleration (quartic) |
ease_out_quart | Gradual deceleration (quartic) |
ease_in_out_quart | Acceleration then deceleration (quartic) |
ease_in_quint | Gradual acceleration (quintic) |
ease_out_quint | Gradual deceleration (quintic) |
ease_in_out_quint | Acceleration then deceleration (quintic) -- default |
bash
# Record a 10-second scroll animation as GIF
curl "https://api.nodium.io/api/v1/screenshot/animate?access_key=KEY&url=https://example.com&format=gif&scenario=scroll&duration=10&scroll_easing=ease_in_out_cubic" -o scroll.gif
# MP4 video with custom scroll settings
curl -X POST "https://api.nodium.io/api/v1/screenshot/animate" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "mp4",
"scenario": "scroll",
"duration": 15,
"scroll_by": 500,
"scroll_duration": 2000,
"scroll_back": true,
"scroll_easing": "ease_in_out_quint"
}' -o video.mp4
Bulk Parameters (/bulk)
The /bulk endpoint accepts a JSON body with the following structure:
| Parameter | Type | Default | Description |
|---|
execute | boolean | false | true = execute all screenshots before responding (eager). false = return URLs that trigger capture on access (lazy). |
optimize | boolean | false | Optimize when multiple requests target the same URL with different parameters. Requires execute=true. |
options | object | -- | Default ScreenshotOptions applied to every request in the batch. |
requests | array | -- | Array of individual ScreenshotOptions objects. Each can override the defaults from options. |
Request format
json
{
"access_key": "KEY",
"execute": true,
"optimize": true,
"options": {
"format": "png",
"viewport_width": 1280,
"viewport_height": 1024,
"block_ads": true
},
"requests": [
{ "url": "https://example.com" },
{ "url": "https://example.com/about", "format": "jpeg" },
{ "url": "https://example.com/pricing", "viewport_device": "iphone_16" }
]
}
Response format
Without execute (lazy):
json
[
{ "url": "https://api.nodium.io/api/v1/screenshot/take?..." },
{ "url": "https://api.nodium.io/api/v1/screenshot/take?..." },
{ "url": "https://api.nodium.io/api/v1/screenshot/take?..." }
]
With execute=true (eager):
json
[
{
"url": "https://api.nodium.io/api/v1/screenshot/take?...",
"response": {
"is_successful": true,
"status": 200,
"body": "<base64-encoded screenshot>"
}
}
]
bash
# Bulk screenshot request
curl -X POST "https://api.nodium.io/api/v1/screenshot/bulk" \
-H "X-Access-Key: KEY" -H "Content-Type: application/json" \
-d '{
"execute": true,
"options": { "format": "png", "block_ads": true },
"requests": [
{ "url": "https://example.com" },
{ "url": "https://example.com/about" },
{ "url": "https://example.com/pricing" }
]
}'
Error Codes
Complete list of all API error codes.
| Error Code | HTTP Status | Description | Recommended Action |
|---|
access_key_required | 400 | Access key is missing. | Provide your API key via header, query parameter, or JSON body. |
access_key_invalid | 400 | Access key is invalid or revoked. | Check your API key in the Dashboard. Generate a new one if needed. |
signature_is_required | 400 | Signed URL is required for this organization. | Generate a signed URL using your signing key. |
signature_is_not_valid | 400 | Signature does not match. | Verify your signing key and the parameter canonical string. |
screenshots_limit_reached | 400 | Monthly quota exceeded. | Upgrade your plan or wait for the next billing period. |
concurrency_limit_reached | 400 | Too many concurrent requests. | Wait for ongoing requests to complete, or upgrade your plan. |
request_not_valid | 400 | Invalid request parameters. | Check the error message for details on which parameter is invalid. |
selector_not_found | 400 | CSS selector not found on the page. | Verify the selector exists. Disable with error_on_selector_not_found=false. |
invalid_cookie_parameter | 400 | Malformed cookie string. | Use the format name=value; Domain=domain. |
invalid_header_parameter | 400 | Malformed header string. | Use the format Header-Name:Header-Value. |
resulting_image_too_large | 400 | Output image exceeds size limits. | Reduce viewport size, disable full_page, or lower device_scale_factor. |
request_body_too_large | 413 | Request body too large. | Reduce the size of html or markdown content. |
name_not_resolved | 400 | DNS resolution failed. | Verify the URL is correct and the domain exists. |
network_error | 500 | Cannot connect to the target URL. | Check if the target is accessible. Retry with exponential backoff. |
host_returned_error | 500 | Target site returned non-2xx status. | Use ignore_host_errors=true to capture anyway. |
timeout_error | 500 | Operation timed out. | Increase timeout, use async=true for long operations, or simplify the request. |
content_contains_specified_string | 500 | Page contains a forbidden string (fail_if_content_contains). | Review the page content or adjust the condition. |
content_missing_specified_string | 500 | Page is missing a required string (fail_if_content_missing). | Review the page content or adjust the condition. |
matched_failed_request | 500 | A network request matching fail_if_request_failed has failed. | Check the target API or adjust the pattern. |
script_triggers_redirect | 400 | Injected script caused a redirect. | Add scripts_wait_until to handle the navigation. |
storage_access_denied | 400 | Cannot access storage service. | Verify your storage credentials in the Dashboard. |
internal_application_error | 500 | Internal server error. Safe to retry. | Retry with exponential backoff. |
temporary_unavailable | 503 | Service is overloaded. Safe to retry. | Wait and retry with exponential backoff. |
Every successful response includes the following headers:
| Header | Description | Example |
|---|
x-nodium-rendering-seconds | Time spent rendering the screenshot (seconds). | 2.34 |
x-nodium-size-bytes | Size of the output file in bytes. | 245760 |
x-nodium-reference | Unique reference ID for this screenshot. | 1234567 |
x-nodium-trace-id | Trace ID for debugging and support requests. | abc123-def456 |
x-nodium-cache-url | Public URL of the cached screenshot (when cache=true). | https://cdn.nodium.io/cache/abc.png |
x-nodium-image-width | Image width in pixels (when metadata_image_size=true). | 1280 |
x-nodium-image-height | Image height in pixels (when metadata_image_size=true). | 1024 |
x-nodium-page-title | Page title (when metadata_page_title=true). | Example Domain |
x-nodium-open-graph | JSON-encoded Open Graph data (when metadata_open_graph=true). | {"title":"..."} |
x-nodium-icon | JSON-encoded favicon info (when metadata_icon=true). | {"url":"...","type":"image/x-icon"} |
x-nodium-http-status-code | Target site HTTP status (when metadata_http_response_status_code=true). | 200 |
x-nodium-http-headers | Target site response headers (when metadata_http_response_headers=true). | JSON-encoded headers |
x-nodium-content-url | URL to extracted content (when metadata_content=true). | https://cdn.nodium.io/content/abc.html |
x-nodium-content-expires | Expiration timestamp for content URL. | 2026-03-06T00:00:00Z |
X-Nodium-Vision-Completion | GPT Vision response (when vision_prompt is set). | The page shows... |
x-nodium-external-identifier | Your custom identifier (webhooks only). | order-12345 |
X-Nodium-Signature | HMAC-SHA256 signature (webhooks only, when webhook_sign=true). | a1b2c3d4... |