Guides · 2026-10-18

Give your AI agent eyes: pairing web search and fetch APIs with screenshots

Web access for agents is turning into a standard part of model APIs. This week DeepSeek launched a Search API and a Fetch API at $0.75 per 1,000 requests. Fetch takes a URL and returns the page as Markdown. Anthropic's API has had web_search and web_fetch tools for a while, and most coding agents ship with something similar.

These tools are good at telling an agent what a page says. To judge how a page looks, the agent needs a screenshot and a model that can read images. This guide covers when that matters and how to add screenshots next to the text tool you already use.

What text fetching misses

  • Layout bugs. A pricing table that overflows on phones, a button hidden behind a sticky header, text over an image you can't read. The Markdown looks fine.
  • Charts, canvases and maps. Dashboards and canvas apps draw their content, so their HTML is mostly empty containers.
  • Text inside images. Hero banners, screenshots of prices, infographics.
  • Whether a deploy actually works. A page can return clean HTML and still render blank because a script failed.
  • Things covering the content. Consent walls, paywalls and modals often sit on top of text that fetch tools report as visible.
  • Design comparisons. "How does our signup page compare with theirs?" is a visual question.

A simple rule for agents

The question is about…UseWhy
Facts, quotes, docs, prices written as textText fetchCheaper per call and far fewer tokens
Layout, design, mobile view, charts, imagesScreenshotOnly pixels show it
"Is this page broken?"BothCompare the expected text with what actually appears

Put this rule in the agent's system prompt or tool descriptions. Agents given both tools without guidance tend to screenshot everything, which costs more tokens and is worse for reading long text.

Option 1: a coding agent (Claude Code, Cursor, VS Code)

Add Shotlane as an MCP server. The agent gets screenshot, read_page and html_to_pdf tools, and you sign in once in the browser:

claude mcp add --transport http shotlane https://shotlane.dev/mcp

For Cursor and VS Code, add an HTTP MCP server with the URL https://shotlane.dev/mcp (setup for every client). Keep using your existing fetch tool for text. DeepSeek's docs say that when you run their models through Claude Code or Codex, web search and fetch calls go to their Search and Fetch APIs; Shotlane adds the screenshots on top. Prompts that work well:

  • "Take a screenshot of https://staging.your-app.dev/pricing at 393 px wide and tell me what's broken." (Shotlane can only reach public addresses, so use a staging URL or a tunnel for local work.)
  • "Screenshot our homepage and theirs on desktop and compare the first screen."
  • "After you deploy, screenshot the changed page and check it matches the design."

Option 2: your own agent, in Python

This script fetches the text with DeepSeek's Fetch API, takes a phone-sized screenshot with Shotlane, and asks a vision model to compare them. Swap any of the three for the provider you use; the pattern is the same.

import base64, os
import anthropic, requests

URL = "https://your-app.dev/pricing"

# 1. Text: DeepSeek Fetch returns the page as Markdown ({"title", "content"})
fetched = requests.post(
    "https://api.deepseek.com/v1/tools/fetch",
    headers={"Authorization": f"Bearer {os.environ['DEEPSEEK_API_KEY']}"},
    json={"url": URL},
    timeout=60,
)
fetched.raise_for_status()
page_text = fetched.json()["content"]

# 2. Pixels: Shotlane renders the page in Chrome at phone size
#    (widths up to 480 px get a mobile user agent automatically)
shot = requests.get(
    "https://shotlane.dev/v1/screenshot",
    params={"url": URL, "width": 393, "height": 852, "hide_cookie_banners": "true"},
    headers={"Authorization": f"Bearer {os.environ['SHOTLANE_KEY']}"},
    timeout=90,
)
shot.raise_for_status()
image_b64 = base64.standard_b64encode(shot.content).decode()

# 3. Ask a vision model about both
client = anthropic.Anthropic()
response = client.beta.messages.create(
    model="claude-opus-5-5",
    max_tokens=16000,
    betas=["server-side-fallback-2026-07-01"],
    fallbacks="default",
    messages=[{"role": "user", "content": [
        {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": image_b64}},
        {"type": "text", "text": "Here is the text of a web page:\n\n" + page_text +
            "\n\nThe screenshot shows the same page on a phone. Is anything from the text "
            "missing, cut off, overlapping or unreadable in the screenshot? Be specific."},
    ]}],
)
if response.stop_reason == "refusal":
    raise SystemExit("The model declined this request.")
print("".join(block.text for block in response.content if block.type == "text"))

To turn this into a tool-using agent, expose the screenshot call as a tool with a description like "Use only for questions about how a page looks: layout, design, mobile view, charts or images. Use fetch for text."

Keeping screenshots cheap

  • Capture the viewport. A 1280×800 capture is enough for most questions. Full-page captures of long pages get downscaled by the model anyway.
  • Crop to what matters. Pass a CSS selector (#pricing, main, .chart) to capture one element.
  • Scale 1. Retina captures (scale=2 or 3) cost more image tokens without helping the model much.
  • Cache repeats. Agents often look at the same page twice. With cache_ttl=3600, repeats within the hour are free on Shotlane.

On price: text fetching is cheaper. DeepSeek charges $0.75 per 1,000 fetches; a Shotlane screenshot costs $1.98 to $4.50 per 1,000 depending on the pack, with credits that don't expire. That's another reason to keep the rule above: fetch for text, screenshot when the question is visual.

Try it without a key

Shotlane answers keyless requests by URL prefix, 20 a day per IP:

curl https://shotlane.dev/shot/https://news.ycombinator.com -o hn.png
curl https://shotlane.dev/md/https://news.ycombinator.com

Agents can read https://shotlane.dev/SKILL.md to set themselves up, including getting a key with your email address.

Skip the browser babysitting

Shotlane runs hardened headless Chromium for you: screenshots and PDFs from one HTTP request, with cookie-banner hiding, ad blocking, signed embed URLs and free cache hits. Prepaid credits that never expire.

100 free renders · no credit card · key shown instantly