Styling and customization
Customize page appearance with dark mode, CSS injection, and timing controls
Styling and customization
Control how pages appear in your screenshots with dark mode emulation, custom CSS injection, and precise timing controls.
Dark mode
Capture pages with dark color scheme:
{
"url": "https://example.com",
"darkMode": true
}This emulates prefers-color-scheme: dark, triggering:
- CSS media queries
- JavaScript-based theme detection
- Framework dark themes (Tailwind, Bootstrap, etc.)
Example
curl -X POST 'https://api.allscreenshots.com/v1/screenshots' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://github.com",
"darkMode": true
}' --output dark-github.pngCompare light and dark
Use composition to show both themes:
{
"url": "https://example.com",
"variants": [
{ "darkMode": false, "label": "Light" },
{ "darkMode": true, "label": "Dark" }
],
"output": {
"layout": "horizontal"
}
}Custom CSS
Inject CSS to modify page appearance:
{
"url": "https://example.com",
"customCss": "body { font-family: 'Inter', sans-serif; }"
}Custom CSS is limited to 10,000 characters.
Common use cases
Change fonts:
{
"customCss": "@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap'); body { font-family: 'Inter', sans-serif !important; }"
}Adjust colors:
{
"customCss": ":root { --primary-color: #007bff; } .brand-element { color: var(--primary-color) !important; }"
}Remove animations:
{
"customCss": "*, *::before, *::after { animation: none !important; transition: none !important; }"
}Highlight elements:
{
"customCss": ".feature-highlight { box-shadow: 0 0 0 4px #ff6b6b !important; border-radius: 8px; }"
}Adjust spacing:
{
"customCss": ".hero-section { padding: 80px 40px !important; } .content { max-width: 800px; margin: 0 auto; }"
}Timing controls
Control when the screenshot is captured for pages with dynamic content.
Wait until
Specify which page load event to wait for:
{
"url": "https://example.com",
"waitUntil": "networkidle"
}| Value | Description |
|---|---|
load | Wait for load event (default) |
domcontentloaded | Wait for DOM to be ready |
networkidle | Wait until network is idle (no requests for 500ms) |
When to use each:
load- Most sites, standard contentdomcontentloaded- Fast capture, static contentnetworkidle- SPAs, lazy-loaded content, API-driven pages
Delay
Add a delay after page load:
{
"url": "https://example.com",
"delay": 2000
}Useful for:
- Animation completion
- Lazy image loading
- JavaScript hydration
- Cookie banner auto-dismiss
Maximum delay is 30,000ms (30 seconds). For longer waits, consider async jobs.
Wait for selector
Wait for a specific element to appear:
{
"url": "https://example.com/dashboard",
"waitFor": ".chart-container.loaded"
}This waits until the CSS selector matches an element in the DOM.
Combine timing options
For complex pages, combine multiple timing controls:
{
"url": "https://example.com/dashboard",
"waitUntil": "networkidle",
"waitFor": "[data-loaded='true']",
"delay": 500
}Order of execution:
- Page loads until
waitUntilevent - Wait for
waitForselector (if specified) - Apply
delay(if specified) - Capture screenshot
Timeout
Set maximum wait time:
{
"url": "https://example.com",
"timeout": 60000
}| Range | Description |
|---|---|
| Minimum | 1,000ms (1 second) |
| Default | 30,000ms (30 seconds) |
| Maximum | 60,000ms (60 seconds) |
Element capture
Capture a specific element instead of the full viewport:
{
"url": "https://example.com",
"selector": "#hero-section"
}The image is automatically cropped to the element's bounding box.
Complex selectors
{
"selector": "main article:first-child"
}{
"selector": "[data-testid='product-card']"
}{
"selector": ".pricing-table .enterprise-plan"
}Examples
Dashboard with charts
curl -X POST 'https://api.allscreenshots.com/v1/screenshots' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://dashboard.example.com",
"waitUntil": "networkidle",
"waitFor": ".chart-loaded",
"delay": 1000,
"customCss": ".loading-spinner { display: none !important; }"
}' --output dashboard.pngHero section only
curl -X POST 'https://api.allscreenshots.com/v1/screenshots' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"selector": "section.hero",
"customCss": ".hero { padding: 60px 0; }"
}' --output hero.pngStyled documentation
curl -X POST 'https://api.allscreenshots.com/v1/screenshots' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://docs.example.com/api",
"darkMode": true,
"customCss": "pre code { font-size: 14px !important; } .sidebar { display: none; } .content { max-width: 100%; }",
"hideSelectors": [".feedback-widget", ".toc"]
}' --output docs.pngBest practices
Test timing settings
Different pages need different timing:
// SPA with lazy loading
const spaSettings = {
waitUntil: 'networkidle',
waitFor: '[data-hydrated]',
delay: 500,
};
// Static marketing page
const staticSettings = {
waitUntil: 'load',
delay: 0,
};Use !important sparingly
Custom CSS should use !important for overrides:
/* May not work */
.element { color: red; }
/* Will override */
.element { color: red !important; }Prefer selectors over CSS hiding
For hiding elements, hideSelectors is cleaner than CSS:
{
"hideSelectors": [".modal", ".banner"]
}vs.
{
"customCss": ".modal { display: none !important; } .banner { display: none !important; }"
}