Metadata-Version: 2.5
Name: langchain-siteshot
Version: 0.1.0
Summary: LangChain tool for the Site-Shot screenshot API: website screenshots from a real Chromium browser, returned as image content for multimodal agents.
Project-URL: Homepage, https://www.site-shot.com/
Project-URL: Documentation, https://www.site-shot.com/blog/langchain-screenshot-tool/
Project-URL: API keys & pricing, https://www.site-shot.com/pricing/
Author-email: Site-Shot <support@site-shot.com>
License: MIT
License-File: LICENSE
Keywords: agents,langchain,langchain-tool,multimodal,screenshot,screenshot-api,site-shot,website-screenshot
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Graphics :: Capture :: Screen Capture
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: <4.0.0,>=3.10.0
Requires-Dist: langchain-core<2.0.0,>=1.0.0
Requires-Dist: site-shot<1.0.0,>=0.3.1
Description-Content-Type: text/markdown

# langchain-siteshot

A LangChain tool that takes website screenshots with the
[Site-Shot](https://www.site-shot.com/) API. The page is rendered in a real
Chromium browser and the image goes back to the model as an image content
block, so a multimodal agent can look at the page.

- Tool name: `capture_screenshot`
- Arguments the model fills in: `url`, `full_page`, `width`, `height`,
  `format` (`png`, `jpeg`, `webp`), `country` (optional)
- Returns a short text block and the image as base64
  (`response_format="content_and_artifact"`). The raw image bytes and capture
  metadata are on `ToolMessage.artifact` and are not sent to the model.
- Built on the official [`site-shot`](https://pypi.org/project/site-shot/) SDK.

## Installation

```bash
pip install -U langchain-siteshot
```

## Credentials

Get a key at <https://www.site-shot.com/start/>. A confirmed account's API
key comes with the free plan: 100 API captures a month, no card needed; paid
plans start at $5/mo for 2,000. Accounts confirmed before 2026-10-30 switch it
on with one button on the dashboard or on `/start/`; an account that has had a
paid plan before does not get the free plan. Plans are listed at
<https://www.site-shot.com/pricing/>.

Set the key as an environment variable, or pass `api_key=` to the tool:

```bash
export SITESHOT_API_KEY="your-api-key"
```

## Quickstart

```python
from langchain_siteshot import SiteShotScreenshot

tool = SiteShotScreenshot()

# With a ToolCall you get a ToolMessage: content for the model, artifact for you.
message = tool.invoke(
    {
        "args": {"url": "https://www.wikipedia.org/", "full_page": True},
        "id": "1",
        "name": tool.name,
        "type": "tool_call",
    }
)
message.content    # [{"type": "text", ...}, {"type": "image", "base64": ..., "mime_type": "image/png"}]
with open("wikipedia.png", "wb") as f:
    f.write(message.artifact["image"])
```

### In an agent

Use a model that accepts images in tool results: Claude, Gemini, or OpenAI
through the Responses API (`ChatOpenAI(..., use_responses_api=True)`). OpenAI's
Chat Completions API takes only text in tool results.

```python
from langchain.agents import create_agent
from langchain_siteshot import SiteShotScreenshot

agent = create_agent(
    model="claude-sonnet-5",
    tools=[SiteShotScreenshot()],
)
agent.invoke(
    {"messages": [{"role": "user", "content": "Take a screenshot of https://www.wikipedia.org/ and describe the layout."}]}
)
```

## Configuration

Settings on the tool are fixed by you and hidden from the model:

| Parameter | Default | Meaning |
| --- | --- | --- |
| `api_key` | `SITESHOT_API_KEY` | Site-Shot API key. |
| `max_concurrency` | `1` | Captures this tool instance runs at the same time. Raise it to your plan's worker count. |
| `full_page_max_height` | `8000` | Height cap in px for full-page captures, so the image fits common vision-model limits. `None` uses the API cap (20000). |
| `default_params` | `{}` | Any other [Site-Shot capture option](https://www.site-shot.com/#documentation), sent on every call, for example `{"no_cookie_popup": True, "no_ads": True, "delay_time": 1500}`. The model's arguments win on conflict. `{"strict_country": False}` allows the API's US fallback (see [Country](#country)). |
| `timeout` | API deadline + 30 s | Client-side deadline in seconds. |
| `handle_tool_error` | `True` | Site-Shot errors come back to the model as an error `ToolMessage` with a plain-language explanation. Set `False` to raise `ToolException` instead. |
| `client` | built from `api_key` | A preconfigured `site_shot.SiteShot` client. |

## Free plan and limits

What the free plan includes:

- 100 API captures a month, no card needed; it renews every month. It comes
  with a confirmed account's key; an account that has had a paid plan before
  does not get it (see [Credentials](#credentials)).
- Renders from the default location or the US only. Any other `country` is
  refused with an error instead of an image, and the refused request still
  counts toward the month's 100. The tool tells the model to retry without
  `country` or with `country="US"`.
- One capture at a time. Agents that issue parallel tool calls would send
  concurrent requests, and a second concurrent request may be refused with
  HTTP 429. That is why `max_concurrency` defaults to 1: calls from one tool
  instance wait for each other instead.
- When the month's captures are used up, the API answers 403 until the plan
  renews, and the tool returns an error message saying so.

Country proxies, storage and schedules are on paid plans from $5/mo. See
<https://www.site-shot.com/pricing/>.

Other limits worth knowing:

- Viewport width 100-8000 px, height 100-20000 px.
- WebP output is capped at 16,383 px per side (a libwebp limit).
- Very tall full-page images can still be large in tokens; lower
  `full_page_max_height` or pass `{"scaled_width": 800}` in `default_params`.

## Country

When a `country` is requested (by the model or in `default_params`), the tool
also sends `strict_country=True`. Without it, Site-Shot silently falls back to
a US vantage point when that country has no capacity, and the model would be
told the page came from a country it did not come from. With it, the capture
fails with `CountryUnavailableError` instead, and the text block's
"rendered from DE" is true. Set `default_params={"strict_country": False}` to
accept the fallback; the text block then says "country requested: DE" and
that the render may have come from the US.

## Errors

The tool maps the SDK's error classes to messages an agent can act on:

| SDK error | When | Message to the model |
| --- | --- | --- |
| `AuthError` | Missing or rejected key | Key rejected; set a valid `SITESHOT_API_KEY`. |
| `QuotaError` | Free plan used up for the month | 100 free-plan captures used; resumes next month or paid plan. |
| `QuotaError` | `country` other than US on the free plan | Geotargeting needs a paid plan; retry without `country` or with US. |
| `QuotaError` (HTTP 429) | Concurrent captures over the plan's limit | Wait and retry; do not capture in parallel. |
| `CountryUnavailableError` | Requested `country` has no capacity right now | No fallback was accepted; retry later or without `country`. |
| `SiteShotTimeoutError` | Page did not finish rendering | Retry once may help. |
| `InvalidParamsError`, `APIError` | Bad parameter, server error | The API's own message. |

Invalid arguments (width out of range, unknown format, a country that is not a
two-letter code) are rejected by the tool's schema before any capture is spent.

## Development

```bash
pip install -e . pytest pytest-asyncio pytest-socket "langchain-tests==1.1.9"
make test                                   # unit tests, network disabled
SITESHOT_API_KEY=... make integration_tests # live API, spends about five captures
```

## License

MIT
