ScreenshotNeo

BlogAI agents

How to Use an AI Agent to Screenshot a Website in Dark Mode

Set a browser’s dark color-scheme preference, guide an AI agent to the right page state, and save a screenshot you can verify.

By the ScreenshotNeo team4 October 20268 min read

To screenshot a website in dark mode with an AI agent, give it the URL, viewport, expected page state, any steps needed to reach that state, and the capture target. In a Playwright browser workflow, emulate a dark color scheme before navigation or capture, wait for the page to settle, then save and inspect the screenshot. A dark preference is only a browser signal: the site must support it, or the agent may need to use the site’s own theme control.

This guide uses Playwright with JavaScript for a runnable workflow, then covers agent prompts, capture choices, verification, troubleshooting, and alternatives. Playwright documents dark color-scheme emulation and viewport, element, and full-page screenshots in its emulation and screenshot guides.

1. Set up Playwright

Use this route when you want direct control over the browser context and a screenshot file on your machine. It launches Chromium, requests dark mode, visits the page, and saves a full-page PNG.

mkdir dark-mode-shot
cd dark-mode-shot
npm init -y
npm install playwright
npx playwright install chromium

Save this as screenshot.mjs:

import { chromium } from 'playwright';

const url = process.argv[2];
if (!url) {
  console.error('Usage: node screenshot.mjs https://example.com');
  process.exit(1);
}

const browser = await chromium.launch({ headless: true });
try {
  const context = await browser.newContext({
    viewport: { width: 1440, height: 1000 },
    colorScheme: 'dark',
    deviceScaleFactor: 1
  });
  const page = await context.newPage();
  page.setDefaultTimeout(15000);

  const response = await page.goto(url, {
    waitUntil: 'domcontentloaded',
    timeout: 45000
  });

  if (!response) {
    throw new Error('Navigation did not return an HTTP response.');
  }
  if (!response.ok()) {
    console.error(`Navigation returned HTTP ${response.status()}`);
  }

  // Allow initial rendering and client-side theme code to run.
  await page.waitForTimeout(1000);

  // If the site has a separate theme toggle, use its accessible name here.
  // Example: await page.getByRole('button', { name: /dark mode/i }).click();

  await page.screenshot({
    path: 'website-dark.png',
    fullPage: true,
    animations: 'disabled'
  });
  console.log(`Saved website-dark.png (HTTP ${response.status()})`);
  console.log(`Final URL: ${page.url()}`);
} finally {
  await browser.close();
}

Run it with node screenshot.mjs https://example.com. The script checks that navigation returned a response, reports non-success HTTP status, and closes the browser even if capture fails. An HTTP 200 does not prove that the right content or theme rendered; review the image.

2. Ask an AI agent for a verifiable capture

Agents do better when the task states the desired appearance and how to verify it. Provide the following details:

  • URL and access: the exact page and whether login or an existing browser session is required.
  • Viewport: desktop or mobile dimensions, and whether device scale matters.
  • Theme state: request a dark color scheme, and mention any site-specific theme toggle.
  • Steps: navigation, consent decisions, menus, or other interactions needed before capture.
  • Target and output: viewport, element, or full page; filename and image format.
  • Evidence: inspect the saved screenshot and report whether the rendered page is actually dark.

Prompt template:

Open https://example.com at a 1440 by 1000 desktop viewport. Emulate a dark color scheme, then wait for the page to finish its initial rendering. If the site has a separate theme toggle, locate it from the accessible page structure and switch it to dark. Capture the full page as website-dark.png. Inspect the saved screenshot and report whether the page actually rendered in dark mode. If not, describe what prevented it. Do not claim success unless the file was saved and reviewed.

Use an accessibility or page snapshot to locate controls and understand structure; use the screenshot to judge visual appearance, including charts, canvas content, spacing, and color. OpenClaw documents browser-agent actions, emulation, snapshots, and screenshots in its browser tools guide. VS Code documents agent browser navigation, inspection, interaction, and screenshots in agent mode documentation. For authenticated pages, check which browser session the agent can access: VS Code’s documented agent-opened sessions are isolated unless an existing tab is explicitly shared.

3. Choose viewport, element, or full-page capture

Capture Use it for Playwright option
Viewport A visible state, responsive check, or bug report await page.screenshot({ path: 'view.png' })
Element A component, chart, card, or isolated visual await page.locator('main article').screenshot({ path: 'article.png' })
Full page A long article or page audit await page.screenshot({ path: 'full.png', fullPage: true })

Playwright’s screenshot workflow also supports custom filenames, PNG/JPEG/WebP output, and high-resolution capture. PNG is the default when no format is specified. High-resolution screenshots use device pixels, so their pixel coordinates do not map directly to CSS-pixel mouse coordinates. For a specific element, make sure it exists and is visible before capturing:

const article = page.locator('main article');
await article.waitFor({ state: 'visible' });
await article.screenshot({ path: 'article-dark.png', type: 'png' });

For a viewport image, choose dimensions that match the question being answered. A mobile-width viewport can expose responsive behavior, but it does not prove the desktop layout is correct. For visual comparisons, keep viewport, device scale, page state, and wait conditions consistent.

4. Make dark mode reliable

Prefer a browser context preference

Set colorScheme: 'dark' when creating the context, as in the runnable example. This applies the preference to the page from the start, which helps sites that choose their theme during initial rendering.

If the page is already open, emulate the media preference before capturing:

await page.emulateMedia({ colorScheme: 'dark' });
await page.waitForTimeout(500);
await page.screenshot({ path: 'after-emulation.png' });

Handle sites with their own theme switch

Some sites ignore the system preference or save a separate light/dark choice. Inspect the page structure, find the theme control by its accessible role and name, and activate it. Then verify the result visually. A label such as “Dark mode” might describe either an action or the current state, so inspect the control and resulting page rather than assuming its meaning.

For a site that uses a stored preference, set storage only when you know the site’s documented key and value. There is no universal local-storage key for dark mode. Avoid guessing: an incorrect value can leave the page unchanged or alter unrelated behavior.

Wait for the right state

domcontentloaded is a useful starting point, but it does not mean every image, font, API request, or client-side theme update has finished. Prefer a specific condition when possible:

await page.getByRole('heading', { name: 'Pricing' }).waitFor();
await page.locator('main').waitFor({ state: 'visible' });

Use a short delay only for effects that have no observable completion condition. Network-idle waits can hang on pages with analytics or long polling, so do not use them as a universal readiness test.

5. Other documented agent routes

  • Playwright directly: the example above offers explicit control of browser preference, viewport, target, and output.
  • VS Code browser tools: useful when the agent is already working in the development environment and needs to navigate, inspect accessible content, interact, and capture. Confirm access to the required authenticated tab.
  • OpenClaw browser tool: its documented browser actions include navigation, interaction, emulation, snapshots, and screenshots.

Pick based on the browser session the agent can reach, its ability to set a dark preference, its capture targets and formats, and whether you need a local runnable script. No pricing comparison is included here because the research for this guide did not establish current prices for these agent tools.

6. Troubleshooting

Symptom Likely cause What to do
The image is still light The site does not follow prefers-color-scheme, or a saved theme setting overrides it. Inspect for a site theme toggle, activate it, then review the captured pixels.
The screenshot is blank or incomplete Capture happened before client rendering, navigation failed, or the page content is behind a delayed state. Check the response status and final URL; wait for a meaningful heading or main element before capture.
The script reports a timeout The page or chosen selector did not reach the expected state in time. Check URL accessibility and selector spelling; use a narrower readiness condition and adjust the relevant timeout.
Theme toggle click fails The control name differs, is hidden, or is not a button. Inspect an accessibility snapshot, identify the actual role and accessible name, and target the visible control.
Login page appears instead The agent’s browser has no access to the user’s signed-in session. Use an authorized shared tab or sign in through the agent’s supported flow; do not assume browser sessions are shared.
Images or fonts are missing They load later, require scrolling, or are blocked by the environment. Wait for the specific assets or state; for lazy-loaded pages, scroll through content before full-page capture if necessary.
Full-page image is unexpectedly huge The document is unusually long or contains expanding content. Capture the relevant element or viewport, or constrain the page state before taking a full-page image.
Colors differ between runs Viewport, device scale, animation, dynamic content, or theme persistence changed. Hold these inputs constant, disable animations for visual comparison, and record the final URL and state.

7. Performance, reliability, and cost

A local Playwright capture uses browser startup, page navigation, and rendering time; large pages and full-page images take more resources than a viewport capture. Keep browser reuse in mind for batches, avoid waiting for irrelevant network activity, and wait for a page-specific condition rather than adding a long fixed sleep. Close the browser in a finally block so failures do not leave a process running.

For repeatable evidence, record the URL, viewport, color-scheme setting, capture target, and any theme-toggle steps. Check HTTP status, final URL, whether the expected content is present, and the actual screenshot. A successful file write alone does not establish that the page rendered correctly. Local Playwright has no per-screenshot API charge, but you are responsible for the machine and browser environment running it.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Send one GET request for an image or PDF; its API documentation describes the available options, including dark mode, viewport and device presets, full-page capture, and element capture.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

For dark mode, add the documented dark-mode option from the API docs to the request. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

Get 1,000 free screenshots a month with no card.

9. FAQ

Does setting dark mode change the website for everyone?

No. It changes the browser preference for that capture context. It does not change the site’s saved theme for other visitors.

Should I capture a screenshot or an accessibility snapshot?

Use a snapshot to understand page structure and find controls; use a screenshot to verify rendered pixels and visual layout.

Can an AI agent confirm the site is truly dark?

It can inspect the saved image and report what it sees. Ask it to distinguish a successfully applied browser preference from a visually dark result.

Which image format should I choose?

PNG is a practical default for UI evidence. Use JPEG or WebP when smaller files matter and their image characteristics suit the content.