ScreenshotNeo

BlogAI agents

How to Use an AI Agent to Screenshot a Webpage with a Particular Language Header

Set a browser locale or an explicit Accept-Language header before navigation, then capture the page with Playwright. Learn what each setting controls and how to troubleshoot the result.

By the ScreenshotNeo team4 October 20268 min read

To screenshot a webpage with a particular language preference, configure the browser before navigating. With Playwright, set locale on the browser context when you want browser-wide locale behavior, or set an explicit Accept-Language request header when a task requires a specific header string. Then navigate, wait for the page content you need, and call page.screenshot().

A language preference is a signal to the site, not a guarantee that it will render translated content. The site may also rely on its URL, a language selector, cookies, or account settings.

1. Choose locale emulation or an explicit header

Approach Use it when What it changes
Browser context locale You want the browser to behave as though it uses a locale such as fr-FR. Playwright documents effects on navigator.language, the Accept-Language request header, and number and date formatting.
page.setExtraHTTPHeaders() A test or integration requires a literal header value such as fr-FR,fr;q=0.9. Adds the header to requests initiated by the page. Configure it before navigation.

These controls are related but not interchangeable. Locale emulation represents a broader browser preference. An explicit header sets the request value you specify; it does not, by itself, guarantee matching browser language state or formatting.

2. Install Playwright

For a local Node.js project, install Playwright and its Chromium browser:

npm init -y
npm install playwright
npx playwright install chromium

Save one of the following examples as a JavaScript file and run it with node filename.js. Replace the target URL and locale or header value as needed.

3. Capture with a browser locale

Set the context locale before creating and navigating the page. This is the usual choice when the intent is to emulate a user’s browser locale.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  try {
    const context = await browser.newContext({ locale: 'fr-FR' });
    const page = await context.newPage();

    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
    await page.screenshot({ path: 'page-fr.png', fullPage: true });
  } finally {
    await browser.close();
  }
})();

fullPage: true captures the full scrollable document. Remove it or set it to false for a viewport screenshot. For an asynchronously rendered page, wait for a meaningful page-specific condition before capturing, for example:

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.locator('main article').waitFor({ state: 'visible' });
await page.screenshot({ path: 'page-fr.png', fullPage: true });

Use a selector that actually identifies the content on your target site. A fixed delay can be used when there is no suitable selector, but it is less reliable than waiting for a known condition.

4. Capture with an exact Accept-Language header

When the required value is specifically an HTTP header, configure it before the first navigation so the initial request uses it.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage();
    await page.setExtraHTTPHeaders({
      'Accept-Language': 'fr-FR,fr;q=0.9'
    });

    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
    await page.screenshot({ path: 'page-fr.png', fullPage: true });
  } finally {
    await browser.close();
  }
})();

Playwright accepts string values for extra headers and sends them with requests the page initiates. It does not guarantee the order of outgoing headers. If you need a precisely specified preference string, provide the entire value you require rather than assuming that setting a locale will produce that exact string.

5. Make the workflow suitable for an AI agent

  1. Collect the target URL and either a locale identifier or the exact header string from the user or task.
  2. Validate that the URL is allowed for the task and that the locale or header value is not empty.
  3. Choose context locale for locale emulation; choose an explicit header for a literal request requirement.
  4. Apply the setting before navigation.
  5. Navigate and wait for a page-specific content condition when the page renders asynchronously.
  6. Save the screenshot to a known path and return that path to the caller.
  7. When correctness matters, inspect the screenshot and verify the request behavior separately. Do not report that the site changed languages based only on the configured preference.

For an agent that handles multiple jobs, use a separate browser context per job when locale or other browser state must not carry over. Close pages, contexts, and the browser in cleanup paths so a failed navigation does not leave browser processes running.

6. Screenshot scope and repeatability

  • Viewport or full page: Playwright captures the viewport by default. Set fullPage: true to capture the full scrollable page.
  • Dynamic content: Wait for a meaningful selector or application state instead of taking the screenshot immediately after navigation.
  • Animations: For repeatable captures, use Playwright’s screenshot animation option to disable animations where appropriate.
  • Unstable or sensitive regions: Playwright’s screenshot API supports masking elements. Masking can make comparisons more stable and prevent selected content from appearing in the artifact.
  • Output: The screenshot path determines where the file is saved. Choose a descriptive path and ensure the agent can return or upload that artifact through its own workflow.

Playwright’s screenshot API also exposes format and scale options. Check the screenshot API documentation for the supported options and exact behavior for the installed Playwright version.

7. Verify what the site actually received and rendered

A configured locale or header expresses a preference; the target site decides how to respond. A site may ignore Accept-Language, use a saved language cookie, require a language-specific URL, or render based on account settings. When the distinction matters:

  • Inspect the screenshot for the expected language and content.
  • Check the request behavior using suitable browser or server-side diagnostics.
  • Account for redirects: the final page may be on another host or path with different language behavior.
  • Do not treat an intercepted request’s partial header view as definitive proof of the final on-wire headers. Some headers are attached by the network stack immediately before transmission and are not reliably exposed or overridden through request routing.

Playwright documents that redirect requests form a chain and that continued-request headers apply across redirect hops, with a cookie exception. Consider the final destination and the site’s own language selection logic when interpreting the capture.

8. Optional: connect to an existing browser

A Playwright-managed browser is the straightforward option for a standalone capture. Connecting over Chrome DevTools Protocol (CDP) can be useful when an existing Chromium browser is required, but Playwright warns that CDP connections have significantly lower fidelity than its own connection protocol. CDP is Chromium-specific. Use it only when you need that existing browser, and validate locale and screenshot behavior in that setup.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its API returns a screenshot or PDF from one GET request, and its MCP tools let AI agents call take_screenshot, get_page_info, and capture_pdf. For its supported capture options and parameter names, see the ScreenshotNeo API documentation.

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

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

ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are never billed, and response headers say which outcome occurred. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

Troubleshooting

Symptom Likely cause What to do
Screenshot is in the site’s default language The site ignores the preference, or uses a URL, cookie, selector, or account setting to choose language. Inspect the rendered page, try the site’s language-specific URL or selector where appropriate, and verify the request separately.
Initial page is not localized but later navigation is The header or locale was configured after the first request. Set the context locale or extra header before page.goto(), then repeat the navigation.
Page content is missing from the screenshot The capture happened before client-side rendering completed. Wait for a page-specific selector or state before calling page.screenshot().
Screenshot stops at the viewport The default capture extent is the viewport. Set fullPage: true if the full scrollable document is wanted.
Header inspection does not show the expected value Inspection may expose only a partial request view; some headers are added by the network stack near transmission. Use a reliable server-side or network diagnostic when exact on-wire verification matters; do not infer it solely from interception output.
Behavior differs after a redirect The destination may apply its own language rules, and redirects create a request chain. Check the final URL and rendered output, and account for the site’s behavior across redirect hops.
CDP-connected capture behaves differently CDP has lower fidelity than Playwright’s own connection protocol. Use a Playwright-managed browser for the standalone workflow, or validate the specific CDP setup.
Browser process remains after an error Cleanup did not run after a failed navigation or capture. Close the browser in a finally block, as in the examples.

Performance, reliability, and cost

A local Playwright capture requires launching or connecting to a browser and downloading the page’s resources. Reuse a browser process for a batch of captures when appropriate, while keeping separate contexts for jobs that need isolated locale or cookies. Prefer condition-based waits to long fixed delays: they reduce unnecessary waiting while avoiding screenshots taken before the content appears. Full-page screenshots may take more work than viewport captures on long documents.

Reliability depends on the target site, network, browser version, and timing of dynamic content. A locale preference does not force translation, and a successful screenshot does not prove a particular header reached the server. Handle navigation and capture errors, close browser resources, and make agents report whether they produced the expected artifact.

Self-hosted Playwright has no per-screenshot API charge in this workflow, but it uses compute, browser dependencies, and engineering time to maintain. A hosted API shifts browser setup and operations to a service and has its own plan limits and billing rules. ScreenshotNeo’s stated plans are Free: 1,000 shots/month; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; and Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Use its billed and page-verdict response headers to distinguish clean captures from non-billable outcomes.

FAQ

Does setting Accept-Language translate a page?

No. It communicates a language preference. The site controls whether and how that preference changes the rendered content.

Should an agent set both locale and the explicit header?

Usually choose the control that matches the requirement. Use locale for browser locale emulation; use an explicit header when a literal header value is required. If a test needs both browser state and a specific wire value, configure and verify both deliberately.

Can a screenshot prove which header was sent?

No. The image shows rendered output, not the request headers. Verify request behavior separately when it is part of the test.

Can I capture only the visible screen?

Yes. The default Playwright screenshot is the viewport; omit fullPage or set it to false.

References