ScreenshotNeo

BlogAI agents

How to Use an AI Agent to Screenshot a Webpage with a Custom User Agent

Set a custom User-Agent before navigation, capture the page with Playwright or Puppeteer, and give the image to your agent for visual analysis.

By the ScreenshotNeo team4 October 20268 min read

To screenshot a webpage with a custom User-Agent, set the User-Agent in your browser automation session before navigating, load the page, then capture the viewport, an element, or the full page. The browser automation tool produces the image; your AI agent can inspect it only if the agent runtime exposes that image to the model.

A User-Agent override changes one part of the browser profile. It does not by itself make the browser equivalent to a physical device or guarantee that a website will serve a particular version. If you need mobile layout, configure the viewport and any other relevant device properties too.

1. Choose how the agent will control the browser

An AI model does not change browser settings on its own. Give it a browser-control tool or write a script using a browser automation library. Playwright and Puppeteer both support setting a User-Agent and taking screenshots; use the API that matches the library available in your runtime.

The examples below use a documentation-style placeholder User-Agent. Replace it with the string appropriate for your test. A custom string can influence server-side content selection, but the target site decides how to interpret it.

2. Playwright: set the User-Agent and capture the page

Install Playwright and its Chromium browser in your project using the official installation instructions. Save this as screenshot.mjs and run it with Node.js.

import { chromium } from 'playwright';

const url = process.argv[2] ?? 'https://example.com';
const userAgent = process.env.CUSTOM_USER_AGENT ?? 'Example custom user agent string';

const browser = await chromium.launch();
try {
  const context = await browser.newContext({
    userAgent,
    viewport: { width: 1280, height: 800 },
  });
  const page = await context.newPage();
  const response = await page.goto(url, {
    waitUntil: 'domcontentloaded',
    timeout: 30_000,
  });

  if (response && !response.ok()) {
    console.error(`Navigation returned HTTP ${response.status()}`);
  }

  await page.screenshot({ path: 'page.png', fullPage: true });
  console.log('Saved page.png');
} finally {
  await browser.close();
}

Run it with node screenshot.mjs https://example.com. To supply a different User-Agent without editing the script, set CUSTOM_USER_AGENT in the environment. The context-level setting applies to pages created in that context, so set it before navigation.

domcontentloaded waits for the initial document parse, not every image, font, or application request. Choose a wait condition to fit the site: wait for a known selector when you need a specific component, add a short delay for a known late-rendering element, or wait for network idle only when the page actually becomes idle. Analytics, polling, streaming, and other long-running requests can make network-idle waits unsuitable.

3. Puppeteer alternative

If your agent runtime uses Puppeteer, set the page’s User-Agent before navigation and then use Puppeteer’s screenshot method. Install the package and browser according to the Puppeteer installation guide.

import puppeteer from 'puppeteer';

const url = process.argv[2] ?? 'https://example.com';
const userAgent = process.env.CUSTOM_USER_AGENT ?? 'Example custom user agent string';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setUserAgent(userAgent);
  const response = await page.goto(url, {
    waitUntil: 'domcontentloaded',
    timeout: 30_000,
  });

  if (response && !response.ok()) {
    console.error(`Navigation returned HTTP ${response.status()}`);
  }

  await page.screenshot({ path: 'page.png', fullPage: true });
  console.log('Saved page.png');
} finally {
  await browser.close();
}

Puppeteer’s page-level override is a different interface from Playwright’s context option. Set the value on the page before loading the target URL.

4. Match the screenshot scope to the task

Capture Use it when Tradeoff
Viewport The question concerns what a visitor sees immediately, or you want a compact visual input. Content below the visible area is omitted.
Element You need a particular chart, card, dialog, or other component. The element must exist and be identifiable after rendering; missing or hidden elements need handling.
Full page You need to review content below the fold or preserve a long page for later inspection. Very tall pages can create large images and take longer to capture or pass to an agent.

For a viewport capture, omit fullPage or set it to false. For an element capture, locate the target with the library’s locator API and call its screenshot method. For example, in Playwright, replace the page screenshot line with:

const chart = page.locator('#chart');
await chart.waitFor({ state: 'visible', timeout: 10_000 });
await chart.screenshot({ path: 'chart.png' });

Use a selector that identifies the intended element on the target page. If the page has several matches, narrow the locator or check the count before capturing.

5. Configure a coherent browser profile

A User-Agent is only one browser or device property. Playwright represents settings such as User-Agent, viewport, screen size, and touch separately, and device presets encode assumptions about a platform. If you are testing a mobile-specific response, match the viewport and any other required emulation settings to the scenario rather than changing only the User-Agent. See Playwright’s emulation guide.

Keep the profile stable across the capture: create the context or page with the intended settings, then navigate. If the page depends on cookies, authentication, locale, or other state, configure that state explicitly as part of the browser session. Do not treat a User-Agent string as proof that the browser has every property of the device it names.

6. Give the screenshot to the AI agent

How the image reaches the model depends on the agent framework. Some browser tools return an image directly; a script can instead save an image and pass its bytes or file reference to a vision-capable model through the framework’s supported interface. The screenshot code alone does not implement that handoff.

Use screenshots for visual questions such as layout, colors, charts, canvas output, or documenting a rendering defect. When the agent also needs page structure or reliable interaction targets, provide a structured accessibility or DOM-facing view alongside the image. Playwright’s Page API documents accessibility snapshots, while its screenshot guidance distinguishes visual inspection from structured page information.

If you are using Playwright MCP, its screenshot tool documentation describes screenshot controls such as target, full-page mode, output type, filename, and scale. The agent tool’s accepted settings depend on that integration.

7. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return a PNG, JPEG, WebP, or PDF, and its API accepts the parameter names used by other screenshot APIs. The API documentation has the request options and response details.

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,
)
r.raise_for_status()
with open("shot.webp", "wb") as f:
    f.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}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

The API’s documented feature set includes custom User-Agent, full-page capture, element capture, viewport and device options, wait conditions, and several output and page-control options. Cookie banners, popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

The free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is on every plan. Create a free ScreenshotNeo account to get started.

8. Troubleshooting

Symptom Likely cause Fix
The page looks the same after changing User-Agent. The site does not vary its response for that value, or another part of the device profile controls the layout. Confirm the override is set before navigation. Check the site’s response behavior and configure a consistent viewport or device profile if needed.
The screenshot is blank or missing dynamic content. The capture ran before the app rendered, or the content is loaded only after interaction or scrolling. Wait for a page-specific selector or state. For lazy-loaded content, scroll through the relevant region before full-page capture.
Navigation times out. The page is slow, or the chosen wait condition waits on requests that never settle. Use a suitable timeout and wait for the specific content needed. Avoid network-idle waits on pages with persistent traffic.
The screenshot is unexpectedly short or excludes content. A viewport screenshot was taken, or the page had not finished adding content. Enable full-page capture and wait for the content that defines the page’s final length.
The screenshot is too large for the agent workflow. A tall full-page image or high pixel scale increases image size. Capture only the relevant element or viewport, or reduce the scale if the tool supports it. Pair the image with structured page data for detail.
The page shows an error or a bot challenge. The target rejected or challenged the browser session; a custom User-Agent alone does not guarantee access. Check the response and page state. Use only access methods permitted for the site and do not assume changing the User-Agent resolves the challenge.

9. Performance, reliability, and cost

Capture time is mainly affected by navigation, the page’s own rendering and network activity, and the amount of content being rasterized. A viewport or element shot usually avoids the image size of a very long page. Use the narrowest wait condition that still guarantees the content you need, and close the browser in a finally block so failures do not leave it running.

For repeatable results, hold the User-Agent and viewport constant, use a page-specific readiness condition, and record the URL, capture settings, and time with the output. A successful browser navigation does not guarantee that a screenshot contains the intended content: inspect the HTTP response where available and verify the target element before capture.

Playwright and Puppeteer are software libraries; these examples do not establish a universal speed or reliability winner. With a self-managed browser, account for the runtime and browser infrastructure you operate. With ScreenshotNeo, only clean shots are billed; its response headers report the verdict and billing status. The free allowance is 1,000 shots per month, and paid plans start at $5 for 3,000.

10. FAQ

Can a custom User-Agent make my browser look exactly like a phone?

No. It changes the User-Agent value, while viewport and other emulated properties are separate. Configure the full profile relevant to the test.

Does taking a screenshot automatically let the AI click the page?

No. A screenshot is visual input. Interaction requires browser-control tools, and structured accessibility or DOM information can provide better targets than pixels alone.

Should I use Playwright or Puppeteer?

Use whichever library your agent runtime already exposes. Both document User-Agent overrides and screenshots; their configuration APIs differ.

Will a website always honor my chosen User-Agent?

No. The site controls its response and may use other signals or return the same content regardless of the value.