Screenshot API for AI Agents

Give your AI agents eyes. SnapAPI lets agents capture screenshots, extract structured data, and render web content via a single REST call — no browser cluster required.

Start Free — 200 Requests

Why AI Agents Need a Screenshot API

AI agents — whether built on LangChain, AutoGen, CrewAI, Claude's tool use, OpenAI's function calling, or custom agent frameworks — increasingly need to interact with the web as part of their task execution. They research competitors, verify claims, read documentation, monitor dashboards, and extract data from web sources. The challenge is that the web is primarily visual and JavaScript-rendered: a naive HTTP fetch returns HTML skeleton markup rather than the actual page content, and even well-structured HTML is difficult for agents to work with compared to structured JSON.

A screenshot API solves half this problem — it gives the agent a visual representation of the page that multimodal models (GPT-4V, Claude 3.5 Sonnet, Gemini Pro Vision) can analyze directly. The agent sends a URL to SnapAPI, receives a screenshot, and passes the image to the vision model for analysis. The model can answer questions about the page content, identify UI elements, extract text from the visual, and reason about the page structure in ways that would require complex HTML parsing to achieve through text alone.

SnapAPI's Extract endpoint goes further — it returns structured JSON from CSS selectors, giving agents clean, parseable data without requiring vision model analysis. For structured data extraction tasks (prices, reviews, contact info, publication dates), the Extract endpoint is more efficient than screenshot + vision analysis, since it produces machine-readable output directly rather than requiring an LLM to parse an image.

LangChain Tool Integration

from langchain.tools import tool
import requests, os, base64

@tool
def screenshot_url(url: str) -> str:
    """Capture a screenshot of a URL and return it as base64 PNG.
    Use this when you need to visually inspect a web page."""
    r = requests.get('https://snapapi.pics/screenshot', params={
        'access_key': os.environ['SNAPAPI_KEY'],
        'url': url,
        'viewport_width': '1440',
        'full_page': '0',
        'format': 'png',
    })
    r.raise_for_status()
    return base64.b64encode(r.content).decode()

@tool
def extract_from_url(url: str, selectors: str) -> str:
    """Extract structured data from a URL using CSS selectors.
    selectors should be a JSON string like: [{"key":"price","selector":".price"}]
    Use this to extract specific data from web pages."""
    r = requests.get('https://snapapi.pics/extract', params={
        'access_key': os.environ['SNAPAPI_KEY'],
        'url': url,
        'selectors': selectors
    })
    r.raise_for_status()
    return r.text  # JSON string

@tool
def scrape_url(url: str) -> str:
    """Get the fully rendered HTML of a URL after JavaScript execution.
    Use this when you need to read the full text content of a page."""
    r = requests.get('https://snapapi.pics/scrape', params={
        'access_key': os.environ['SNAPAPI_KEY'],
        'url': url,
        'wait_for': 'body',
    })
    r.raise_for_status()
    # Return a truncated version to stay within context limits
    return r.text[:8000]

# Register with your agent
tools = [screenshot_url, extract_from_url, scrape_url]

Claude Tool Use Integration

import anthropic, requests, os, base64

client = anthropic.Anthropic()

tools = [
    {
        "name": "screenshot_url",
        "description": "Capture a screenshot of any URL and return it as a base64 image. Use this to visually inspect web pages, check UI layouts, or analyze page content visually.",
        "input_schema": {
            "type": "object",
            "properties": {
                "url": {"type": "string", "description": "The URL to screenshot"},
                "full_page": {"type": "boolean", "description": "Whether to capture the full page height", "default": False}
            },
            "required": ["url"]
        }
    },
    {
        "name": "extract_web_data",
        "description": "Extract structured data from a web page using CSS selectors. Returns JSON.",
        "input_schema": {
            "type": "object",
            "properties": {
                "url": {"type": "string"},
                "selectors": {
                    "type": "array",
                    "items": {"type": "object",
                              "properties": {"key": {"type": "string"}, "selector": {"type": "string"}}}
                }
            },
            "required": ["url", "selectors"]
        }
    }
]

def handle_tool_call(name, tool_input):
    if name == "screenshot_url":
        r = requests.get('https://snapapi.pics/screenshot', params={
            'access_key': os.environ['SNAPAPI_KEY'],
            'url': tool_input['url'],
            'full_page': '1' if tool_input.get('full_page') else '0',
        })
        img_b64 = base64.b64encode(r.content).decode()
        return [{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": img_b64}}]

    elif name == "extract_web_data":
        import json
        r = requests.get('https://snapapi.pics/extract', params={
            'access_key': os.environ['SNAPAPI_KEY'],
            'url': tool_input['url'],
            'selectors': json.dumps(tool_input['selectors'])
        })
        return [{"type": "text", "text": r.text}]

# Agentic loop
messages = [{"role": "user", "content": "What does the pricing page at stripe.com look like? Extract the plan names and prices."}]
while True:
    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=4096,
        tools=tools,
        messages=messages
    )
    if response.stop_reason == "end_turn":
        print(response.content[0].text)
        break
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            result = handle_tool_call(block.name, block.input)
            tool_results.append({"type": "tool_result", "tool_use_id": block.id, "content": result})
    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": tool_results})

OpenAI Function Calling Integration

import openai, requests, os, base64, json

client = openai.OpenAI()

functions = [
    {
        "name": "screenshot_url",
        "description": "Capture a screenshot of a URL. Returns base64-encoded PNG.",
        "parameters": {
            "type": "object",
            "properties": {"url": {"type": "string"}},
            "required": ["url"]
        }
    }
]

def run_agent(user_message):
    messages = [{"role": "user", "content": user_message}]
    while True:
        resp = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            functions=functions,
            function_call="auto"
        )
        msg = resp.choices[0].message
        if msg.function_call:
            args = json.loads(msg.function_call.arguments)
            r = requests.get('https://snapapi.pics/screenshot', params={
                'access_key': os.environ['SNAPAPI_KEY'],
                **args
            })
            result = base64.b64encode(r.content).decode()
            messages.append(msg)
            messages.append({"role": "function", "name": msg.function_call.name, "content": result})
        else:
            return msg.content

Agentic Workflows: Screenshot + Vision Analysis

The most powerful pattern combines SnapAPI with a vision-capable LLM for automated visual analysis. The agent captures a screenshot, passes it to the vision model, and uses the model's analysis to drive further actions. Common workflows include: competitor price monitoring (screenshot pricing page weekly, vision model extracts prices in structured format, store to database for trend analysis); visual QA testing (screenshot production pages after deploy, vision model describes what changed compared to baseline description, alert if anomalies are found); content moderation (screenshot flagged URLs, vision model assesses content for policy violations without human reviewer needing to visit the URL directly); and automated accessibility auditing (screenshot pages at various viewport sizes, vision model identifies obvious accessibility issues such as low-contrast text or missing focus indicators).

For workflows requiring multiple sequential page visits — navigating through a multi-step flow, following links, or monitoring paginated content — build an agent loop that calls SnapAPI for each URL in the sequence. Each screenshot is passed to the vision model, which identifies the next URL to visit and extracts any relevant data from the current page. This pattern handles arbitrarily complex navigation workflows without requiring a stateful browser session on your infrastructure.

Give Your AI Agents Web Vision

200 free requests/month. Screenshot + extract + scrape endpoints. Works with any agent framework.

Get Free API Key

Frequently Asked Questions

Can I use SnapAPI screenshots directly with multimodal LLMs?

Yes — pass the screenshot bytes as a base64-encoded image in the model's messages. For Claude, use the image content block type with source.type: "base64". For GPT-4V/GPT-4o, use the image_url content type with a base64 data URL (data:image/png;base64,...). For Gemini Pro Vision, use the inline image format in the parts array. All major multimodal models accept base64 PNG or JPEG directly.

How do I limit screenshot size for LLM context windows?

Use viewport screenshots instead of full-page (omit full_page=1) and set a reasonable viewport size (1280x800 is standard). Request JPEG format with quality 70-80 for smaller file sizes — this reduces the base64 payload significantly while maintaining sufficient quality for LLM analysis. For very long pages, consider the clip parameters to capture just the above-the-fold content or a specific section relevant to the agent's task.

Is there a rate limit that would affect high-frequency agent workflows?

Yes — each plan has a monthly request limit. For high-frequency agents that capture many screenshots per task, monitor your usage via the SnapAPI dashboard and upgrade to a higher plan if needed. Implement caching for URLs that are visited repeatedly within an agent session — pass cache=1&cache_ttl=300 for URLs where a 5-minute-old screenshot is acceptable, reducing API usage significantly for repeated analysis workflows.

Error Handling and Retry Logic for Agent Screenshot Tools

Production AI agents that call external APIs need robust error handling to avoid task failures that propagate up the agent loop. For SnapAPI calls inside agent tools, implement exponential backoff with jitter: on a 429 rate limit response, wait between 1 and 4 seconds before retrying; on a 5xx server error, retry up to three times with doubling delays. Wrap the HTTP call in a try/except that catches connection timeouts separately from API errors — a timeout usually indicates a slow-loading page and warrants a longer delay parameter on retry rather than an immediate second attempt. Return structured error objects from your tool function rather than raising exceptions, because most agent frameworks (LangChain, LlamaIndex, Claude tool_use) handle tool return values more gracefully than exceptions thrown mid-tool-call. A return value like {"error": "timeout", "url": url, "suggestion": "retry with delay=5000"} gives the LLM enough context to decide whether to retry, skip, or ask the user for clarification.

Caching Screenshots in Long-Running Agent Sessions

Agents that research multiple web sources in a single session will frequently revisit the same URLs — a competitive analysis agent might screenshot a competitor homepage five times across different subtasks. Implement a simple in-memory URL-to-image cache keyed by URL and a TTL of ten to thirty minutes. Before calling the SnapAPI screenshot endpoint, check the cache; on a hit, return the cached binary directly. This eliminates redundant API calls, reduces per-session cost, and speeds up agent execution since cached responses are instant. For agents that run as serverless functions or across distributed workers, use Redis or S3 as the shared cache backend with the URL as the cache key and a signed URL pointing to the stored screenshot as the value. This pattern is particularly valuable for monitoring agents that check the same set of pages repeatedly on a schedule — the cache absorbs burst requests while the agent processes and compares results.