Skip to content
ExplainerBy 11 min read

Screenshots for AI agents: how to let a model see a web page

A model can be handed a page as a screenshot, as HTML, as text or as an accessibility tree. This page shows which to choose, what a screenshot costs in tokens at each vendor, and how to connect a screenshot tool, told through one conversation between a person and an agent.

  1. User: On a phone, is the button visible without scrolling?

  2. Tool calltake_screenshot 390 × 844
  3. Tool resultimage/jpeg, read by the model as 434 visual tokens

  4. Agent: Yes. It sits under the first plan, on the first screen.

Read the conversation with notes
Illustrative exampleNot a recording. Token counts are computed, the file size and quota are invented.

What happens when an agent looks at a web page?

An AI agent sees a web page through a tool call: the model asks for a screenshot, a service renders the page in a real browser, and the image comes back as part of the next message. Five messages, each with a note on what it means.

  1. User

    Our pricing page is at https://example.com/pricing. On a phone, can people see the "Start free" button without scrolling?

    Note on step 1: Why a screenshot and not the HTML. Whether a button lands on the first screen depends on fonts, images, spacing and whatever sits above it. The HTML source lists the button but not where it ends up. Only a rendered page answers a question about layout.

  2. Agent

    I will look at the page the way a phone shows it.

    Note on step 2: The model decides to look. The agent has a screenshot tool in its tool list. It reads the tool description and chooses the arguments itself: nobody wrote this call by hand.

  3. Tool callsent by the agent

    {
      "name": "take_screenshot",
      "arguments": {
        "url": "https://example.com/pricing",
        "viewport_width": 390,
        "viewport_height": 844
      }
    }

    Note on step 3: What size was requested. A 390 by 844 window and only the first screen, because full_page is off unless asked for. Through the CurlShot MCP server the format defaults to jpeg and ads and cookie banners are blocked, so no banner covers the button.

  4. Tool resultreturned to the agent

    content[0] · type: text

    Captured https://example.com/pricing, 390 x 844 px, 41 KB, image/jpeg, 86 screenshots left this period. Download: https://curlshot.com/api/v1/files/… (valid for about a day)

    content[1] · type: image · mimeType: image/jpeg

    What the model receives
    The screenshot itself, as base64 data. Drawn here as a placeholder.
    Size
    390 × 844 px
    Claude visual tokens
    14 × 31 = 434

    Note on step 4: What it cost. One screenshot of the account quota. For the model, the image is 14 × 31 = 434 visual tokens on Claude, 422 tokens on the OpenAI patch models, and about 1,120 on Gemini 3 at its default resolution. The file size (41 KB here, an invented figure) does not change the token count: pixels do.

  5. Agent

    Yes. On a 390 by 844 screen the "Start free" button sits under the first plan and is fully on the first screen. The second plan starts below the fold.

    Note on step 5: The answer comes from pixels. The model read the image and answered from what it saw. Anything it read on that page is data from a stranger, not an instruction: see the safety note further down.

Screenshot, HTML, markdown or accessibility tree: which should a model get?

There are four ways to show a web page to a language model, and a screenshot is the right one only when the question is visual. For reading a long article, a screenshot is the wrong choice: extracted text is smaller, exact and cannot be misread.

Show the table
Four ways to show a web page to a model
WayWhat the model getsWhat it missesRelative sizeBest for
ScreenshotWhat the model getsThe page as a person sees it: layout, colour, images, charts, what is cut off or overlapping.What it missesLink addresses, hidden text, anything below the captured area. Small text can be misread.Relative sizeFixed by pixel size, not by how much text is on the page. About 400 to 1,700 tokens for one viewport (table below).Best forQuestions about how a page looks: visual checks, design review, charts, "is this broken?".
Raw HTMLWhat the model getsEvery element, attribute, link address and inline script, exactly as served.What it missesWhat it looks like. Content drawn later by JavaScript is absent unless the HTML is taken after rendering.Relative sizeThe largest. Markup, scripts and styles ride along with the words, and it grows with the page.Best forFinding selectors, reading attributes and structured data, debugging markup.
Extracted text or markdownWhat the model getsThe words, headings, lists, tables and links, with the markup stripped.What it missesLayout, images, charts, colour. Extraction can drop or reorder content on complex pages.Relative sizeThe smallest for text: roughly the words on the page.Best forReading: articles, documentation, long pages, anything you want quoted exactly.
Accessibility treeWhat the model getsOne entry per element with its role, name, description and state: "button, Start free".What it missesAppearance and position. It is only as good as the semantics of the page.Relative sizeIn between: smaller than the HTML, larger than plain text.Best forActing on a page: deciding what can be clicked, typed into or toggled.

The accessibility tree is the structure a browser builds for assistive technology: each object has a name, a description, a role and a state.[8] CurlShot makes the screenshot. It does not extract text or an accessibility tree from a page.

Pick by the question the agent has to answer

  • “Does it look right?”

    Screenshot

    Only pixels show overlap, clipping, contrast and broken images.

  • “What does it say?”

    Text or markdown

    Exact words at the lowest cost. A screenshot of a long article is the wrong choice.

  • “What can I do here?”

    Accessibility tree

    Roles and names tell an agent what is a button, a field or a link.

  • “Why is it built this way?”

    Raw HTML

    Attributes, selectors and embedded data are only in the source.

How many tokens does a screenshot cost?

The token cost of a screenshot is set by its pixel dimensions and by the model, never by its file size. Anthropic and OpenAI publish a formula. Google publishes a fixed figure per resolution level for Gemini 3. Below is what each documentation page said on .

These rules change, and they differ by model

Each vendor documents more than one rule, depending on the model generation, and the pages are revised often. Treat the numbers here as a dated reading of the linked pages, and re-check the source before you budget.
  • Anthropic · Claude[1][2]

    Claude views an image in 28 × 28 pixel patches, and each patch is one visual token.

    tokens = ⌈width / 28⌉ × ⌈height / 28⌉

    • High-resolution tier, "Claude 4.7 and later models": long edge up to 2576 px and up to 4784 visual tokens.
    • Standard tier, "All other models": long edge up to 1568 px and up to 1568 visual tokens.
    • A larger image is scaled down to the largest size that fits both limits, keeping its aspect ratio. The documentation gives a reference implementation, used for the table below.
    • The token limit usually bites first: a 1920 × 1080 screenshot becomes 1456 × 819 on the standard tier, not 1568 × 882.
    • Hard limit: 8000 × 8000 px per image. A request with more than 20 images gets a stricter per-image limit, and Anthropic advises keeping each side at 2000 px or less there.
  • OpenAI · GPT models[3]

    Newer models count 32 × 32 pixel patches and multiply by a model factor. Older models count 512 px tiles on top of a base cost.

    patch models: tokens = ⌈⌈width / 32⌉ × ⌈height / 32⌉ × multiplier⌉ · tile models: tokens = base + tiles × tile tokens

    • The multiplier is 1.2 for gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4 and gpt-5.2, and 1.62 for gpt-4.1-mini.
    • The detail parameter (low, high, original or auto) sets the resizing. For gpt-6-astra, high scales the image down to a 2,500-patch budget, and auto, the default, behaves like original: no downscaling.
    • An image that still needs more than 30,000 patches is rejected, not resized.
    • Tile models: gpt-4o and gpt-4.1 cost 85 base tokens plus 170 per tile, gpt-5.1 costs 70 plus 140. The image is first fitted into 2048 × 2048, then its shortest side is scaled to 768 px.
    • With detail: low a tile model charges only its base tokens, whatever the size.
  • Google · Gemini[4][5]

    On Gemini 3 models the token count of an image is set by the media_resolution level, not by its pixel size.

    Gemini 3: low 280 · medium 560 · high 1120 · ultra_high 2240 · unspecified (default) 1120

    • The documentation calls these "approximate token counts" and the "maximum number of tokens allocated per input image".
    • It recommends high (1120) for most image analysis, and names ultra_high (2240) for computer use.
    • The image understanding page also gives a tile rule without naming a model: 258 tokens when both sides are 384 px or less, otherwise 768 × 768 tiles at 258 tokens each.
    • Google describes its tile count formula as "rough" and does not state the rounding, so the table below uses only the Gemini 3 media_resolution figure.

Worked examples: five capture sizes under six documented rules

Each cell is computed with the vendor's published formula, with the arithmetic under the result. In the OpenAI patch columns it reads patches first, then the 1.2 multiplier. “Resized” means the provider scales the image down before the model sees it.

Show the table
Input tokens for one screenshot, by capture size and vendor rule
CaptureClaude, standard tier[1]Claude, high-resolution tier[1]OpenAI patches, detail high[3]OpenAI patches, detail auto[3]OpenAI tiles, detail high[3]Gemini 3, default resolution[5]
Phone viewport390 × 844 px43414 × 3143414 × 3142213 × 27 = 351, × 1.242213 × 27 = 351, × 1.242585 + 2 × 1701,120fixed by media_resolution
Small desktop viewport1024 × 768 px1,03637 × 281,03637 × 2892232 × 24 = 768, × 1.292232 × 24 = 768, × 1.276585 + 4 × 1701,120fixed by media_resolution
Laptop viewport1280 × 800 px1,33446 × 291,33446 × 291,20040 × 25 = 1,000, × 1.21,20040 × 25 = 1,000, × 1.21,10585 + 6 × 170resized to 1228 × 7681,120fixed by media_resolution
Default viewport of the API1280 × 1024 px1,54044 × 35resized to 1225 × 9801,70246 × 371,53640 × 32 = 1,280, × 1.21,53640 × 32 = 1,280, × 1.276585 + 4 × 170resized to 960 × 7681,120fixed by media_resolution
Full page, 6,000 px tall1280 × 6000 px67212 × 56resized to 335 × 15681,84020 × 92resized to 550 × 25762,98123 × 108 = 2,484, × 1.2resized to 736 × 34499,02440 × 188 = 7,520, × 1.276585 + 4 × 170resized to 436 × 20481,120fixed by media_resolution
Claude, standard tier:
all other Claude models
Claude, high-resolution tier:
Claude 4.7 and later models
OpenAI patches, detail high:
gpt-6-astra with detail: high
OpenAI patches, detail auto:
gpt-6-astra with detail: auto or original (auto is the default)
OpenAI tiles, detail high:
gpt-4o and gpt-4.1 with detail: high or auto
Gemini 3, default resolution:
Gemini 3 models, media_resolution unspecified
Input tokens for one screenshot, all bars on one scale. The outlines are the captures drawn to scale, 1 px for every 50 px. A tall full-page capture either costs several times more (OpenAI at default detail) or is shrunk until its text is small (Claude, and OpenAI at detail high).

What the table shows

A 390 × 844 phone viewport costs about a third of a laptop viewport on Claude and OpenAI. The 1280 × 1024 default is 1,702 Claude tokens, just past the 1568 limit of the standard tier, so it is resized to 1225 × 980. A 1280 × 800 viewport is not.

From tokens to money

Multiply by the input price of your model. Anthropic's own example: at Claude Haiku 4.5's $1 per million input tokens, a 1000 × 1000 image (1,296 tokens) costs about $1.30 per thousand images.[1] By the same arithmetic the phone viewport is 434 × $1 / 1,000,000, about $0.43 per thousand.

What size screenshot should you send to an LLM?

Send the smallest screenshot that answers the question: one viewport, no banners, cropped to the part that matters. Seven rules, each with the option that does it in the CurlShot API.

  1. Capture the viewport, not the whole page

    A 1280 × 6000 full-page capture is scaled down to 335 × 1568 on the Claude standard tier, about a quarter of its width, and body text stops being readable. At OpenAI's default detail on gpt-6-astra the same image costs 9,024 tokens.

    Leave full_page off. It is false by default.

  2. Stay inside the size the model sees natively

    A 1280 × 800 capture is 1,334 visual tokens and passes through the Claude standard tier untouched. The 1280 × 1024 default is 1,702 and gets downscaled to 1225 × 980. If the provider resizes for you, you lose sharpness you paid to render.

    viewport_width, viewport_height

  3. Block cookie banners and ads

    A consent banner covers the content the question is about, and an ad is text the model may read as part of the page. Both cost the same tokens as real content.

    block_cookie_banners=true, block_ads=true (on by default through MCP, off by default in the HTTP API)

  4. Use a phone viewport for dense reading

    At 390 px wide a responsive page reflows into one column, so text stays large relative to the image, and the capture is only 434 Claude tokens. Set the size yourself: a device preset such as iphone_14 renders at 3 device pixels per CSS pixel, which makes a 1170 × 2532 image.

    viewport_width=390&viewport_height=844, or a viewport_device with device_scale_factor=1

  5. Crop to the element in question

    A screenshot of only the pricing table is smaller and removes everything the model could be distracted by. The image is exactly as big as the element.

    selector, or clip_x, clip_y, clip_width, clip_height

  6. Pick the format for legible text

    Tokens are counted from pixel dimensions, so the format changes the upload size, not the token cost. PNG is lossless. JPEG and WebP are much smaller, but heavy compression blurs small text, which Anthropic warns can hurt model performance.

    format=png, or format=jpeg / webp with image_quality (1 to 100, default 80)

  7. Cache repeat looks

    Agents often look at the same page several times in one task. A stored copy comes back faster and does not use a screenshot of the quota. Leave it off when the agent is checking a change it just made.

    cache=true (a copy is kept for 4 hours unless cache_ttl says otherwise)

Sizes and limits in the first two rules come from Anthropic's and OpenAI's documentation.[1][2][3] The option names and defaults are those of the CurlShot API: see capturing an element for selector and the clip rectangle.

How to wire a screenshot tool into an agent

An agent gets screenshots in one of two ways: your code calls an HTTP API and attaches the image to the next message, or the model calls a tool on an MCP server itself. A third surface, machine-readable pages, tells the agent how to do either.

1A plain HTTP request

One GET request returns the image file. Your code sends it to the model as an image part. The first request below asks for one small, clean viewport as a JPEG. The second captures a single element. Every option is a query parameter, and the full list is in the screenshot API overview.

Request
curl "https://curlshot.com/api/v1/screenshot?url=https://example.com&viewport_width=1024&viewport_height=768&format=jpeg&block_ads=true&block_cookie_banners=true" \
  -H "X-Access-Key: YOUR_ACCESS_KEY" \
  --output page.jpg

curl "https://curlshot.com/api/v1/screenshot?url=https://example.com&selector=h1&format=png" \
  -H "X-Access-Key: YOUR_ACCESS_KEY" \
  --output heading.png

2The MCP server

MCP, the Model Context Protocol, carries JSON-RPC messages over stdio or streamable HTTP.[7] The CurlShot server is one endpoint, https://curlshot.com/api/mcp, over streamable HTTP with no session: every POST stands alone. Most clients take a configuration like this one.

MCP client configuration
{
  "mcpServers": {
    "screenshots": {
      "type": "http",
      "url": "https://curlshot.com/api/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_ACCESS_KEY"
      }
    }
  }
}
Show the table
The two tools of the MCP server
ToolNeeds a keyWhat it doesArguments
take_screenshotYesRenders a public web page and returns it as an image part (base64) plus a one-line text summary with a download link.url (required), format, full_page, viewport_device, viewport_width, viewport_height, dark_mode, block_ads, block_cookie_banners, selector, wait_until, delay, cache
list_devicesNoReturns the device presets that viewport_device accepts, with their sizes. Costs nothing.none

Through MCP, format defaults to jpeg and both blocking options default to true, to give an agent a small, clean screenshot. In the HTTP API the defaults are png and false.

A file over 6 MB comes back as a download link, not inline data. A model cannot look at a link, so keep the screenshot small. The guide for AI agents covers the response format, errors and limits.

The same tool call, by hand
curl -X POST "https://curlshot.com/api/mcp" \
  -H "Authorization: Bearer YOUR_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "take_screenshot",
    "arguments": {
      "url": "https://example.com",
      "viewport_width": 390,
      "viewport_height": 844,
      "format": "webp"
    }
  }
}'

3Machine-readable pages

An agent that has never seen an API can learn it from plain text. CurlShot serves these addresses for that purpose, and they are a pattern worth copying on your own site.

Show the table
Machine-readable addresses
AddressWhat it is
/llms.txtA short map of the site for language models, one line per page.
/llms-full.txtEvery docs page in one file.
/agent-mdHow an agent should call the API, on one markdown page.
/openapi.jsonThe API described in OpenAPI 3.1, for tools that generate clients.
/.well-known/mcp.jsonA card for the MCP server: its address, how to sign in and its tools.
any page + .mdThe markdown twin of a docs, tool, pricing or blog page. The same pages answer with markdown when the request says Accept: text/markdown.

Can a screenshot carry a prompt injection?

Yes. A screenshot contains whatever text the page shows, and a vision model reads all of it, including a line written to look like an instruction. Treat what the model reads on a page as untrusted data.

“Indirect prompt injections occur when an LLM accepts input from external sources, such as websites or files.”
OWASP, LLM01:2025 Prompt Injection.[6] The same entry warns that attackers could exploit interactions between modalities, “such as hiding instructions in images”.
  • Label it as untrusted

    Tell the model, in the system prompt, that anything it reads in a screenshot or a web page is content to report on, never a command to follow.

  • Give the agent the least it needs

    A screenshot tool that can only fetch public pages cannot leak much. Keep tools that send email, spend money or read private data out of the same loop, or behind a confirmation.

  • Ask a person before risky actions

    If what the agent saw leads to an action with consequences, a human approves it first.

  • Check the output shape

    When you expect "yes or no and a reason", validate that in code. An answer that suddenly contains a link or a request is a signal.

The four practices follow the mitigations OWASP lists for prompt injection: segregate and identify external content, enforce least privilege, require human approval for high-risk actions, and define and validate expected output formats.[6]

Glossary: the terms on this page

Vision model
A language model that accepts images as input and can describe or reason about what is in them. It reads a screenshot directly, without a separate text recognition step.
Multimodal
Able to take more than one kind of input in the same request, for example text and images together.
Token
The unit a model counts input and output in, and the unit you are billed in. For an image, vendors convert pixels to tokens with a published rule: Claude counts 28 px patches, the newer OpenAI models count 32 px patches.
MCP
Model Context Protocol: an open standard for how an AI application discovers and calls tools. Messages are JSON-RPC, carried over stdio or over streamable HTTP.
Tool call
A structured message in which the model asks its host program to run a named function with arguments, for example take_screenshot with a url. The result comes back as the next message.
Accessibility tree
The structure a browser builds for assistive technology. Each object has a name, a description, a role and a state, such as a button named "Start free".
Viewport
The visible area of a page in the browser window, measured in CSS pixels. A viewport screenshot captures only that first screen. A full-page screenshot captures everything down to the bottom.

Questions people ask

Should I give an AI agent a screenshot or the HTML of a page?

It depends on the question. A screenshot shows layout, colour, images and charts, so use it for anything about how the page looks. Extracted text or markdown is smaller and exact, so use it for reading articles or documentation. Raw HTML is the largest and is for selectors and attributes. The accessibility tree is for deciding what an agent can click or type into.

How many tokens does a screenshot use?

It depends on the pixel size and the model. On Claude the documented formula is ⌈width / 28⌉ × ⌈height / 28⌉, so a 1280 × 800 screenshot is 46 × 29 = 1,334 tokens and a 390 × 844 one is 434. On OpenAI's patch models it is ⌈width / 32⌉ × ⌈height / 32⌉ × 1.2, so 1,200 and 422. On Gemini 3 it is about 1,120 per image at the default media resolution. These are the rules as documented on 11 October 2026.

What screenshot size is best for an LLM?

One viewport that the provider does not have to shrink. 1280 × 800 or 1024 × 768 fits the Claude standard tier untouched (1568 px long edge and 1568 visual tokens). For reading dense text, a 390 × 844 phone viewport keeps text large and costs about a third as much. Crop to one element when the question is about one part of the page.

Can a model read a full-page screenshot?

Often not well. A 1280 × 6000 full-page capture is scaled down to 335 × 1568 on the Claude standard tier and 550 × 2576 on the high-resolution tier, which makes body text tiny. On gpt-6-astra with the default detail it is kept at full size and costs 9,024 tokens. For a long page, send several viewport captures or the page text instead.

Does PNG, JPEG or WebP change the token cost of a screenshot?

No. Anthropic, OpenAI and Google all document image tokens as a function of pixel dimensions or a resolution setting, not file size. The format changes how many bytes you upload and how sharp small text is. PNG is lossless, and JPEG or WebP at a high quality setting is much smaller and usually still legible.

How do I connect a screenshot tool to an agent with MCP?

Add the server to your MCP client configuration with its address and an Authorization header that carries your access key. CurlShot serves MCP at /api/mcp over streamable HTTP, with two tools: take_screenshot (url plus options such as viewport_width, selector and format) and list_devices. The client lists the tools and the model calls them when it needs to see a page.

Can a screenshot contain a prompt injection?

Yes. A model reads any text that is visible in the image, including text written to look like an instruction. OWASP describes this as indirect prompt injection (LLM01:2025) and notes that instructions can be hidden in images. Treat what the model reads on a page as untrusted data, limit what the agent is allowed to do, and require human approval for risky actions.

Sources

  1. [1]Anthropic, Claude API documentation, Vision: image limits, resolution and token cost. Checked .
  2. [2]Anthropic, Claude API documentation, Coordinates and bounding boxes: how Claude resizes and pads images. Checked .
  3. [3]OpenAI, API documentation, Images and vision: calculating costs. Checked .
  4. [4]Google, Gemini API documentation, Image understanding: token calculation. Checked .
  5. [5]Google, Gemini API documentation, Media resolution: token counts. Checked .
  6. [6]OWASP Gen AI Security Project, LLM01:2025 Prompt Injection. Checked .
  7. [7]Model Context Protocol, Transports (specification 2025-06-18). Checked .
  8. [8]MDN Web Docs, Accessibility tree. Checked .

Screenshot any page in one step

Paste an address into CurlShot and download the screenshot. A free account gives you 100 screenshots every month. No card needed.