For AI agents: Copy the reference block below (~12k tokens) into your project as context for your coding agent (Claude, Cursor, Copilot, etc.), then prompt: “Help me integrate Yutori into my project.”
Copy
## Overview
[Yutori](https://yutori.com/) builds web agents that reliably and autonomously execute tasks on the web. There are four APIs:
| API | Description | Use case |
|-----|-------------|----------|
| **n1** | Pixels-to-actions LLM for browser control | Build your own browser agent with your own infra |
| **Browsing** | One-time cloud browser automation | Automate a browser task without managing infra |
| **Research** | Deep one-time web research | Research any topic across the web |
| **Scouting** | Continuous scheduled web monitoring | Monitor the web for changes on a schedule |
**Base URL:** `https://api.yutori.com`
**Authentication:** All requests require an API key via `X-API-Key` header or `Authorization: Bearer <key>`. Keys start with `yt-` and can be created at [platform.yutori.com/settings](https://platform.yutori.com/settings). Every new account gets **$5 in free credits**.
---
## REST API Reference
### n1 API — `POST /v1/chat/completions`
n1 is a pixels-to-actions LLM that processes screenshots and predicts browser actions. It follows OpenAI's Chat Completions interface.
**Models:** `n1-latest` (recommended), `n1-experimental`, `n1-20260203`
```python
from openai import OpenAI
client = OpenAI(
base_url="https://api.yutori.com/v1",
api_key="YOUR_API_KEY",
)
response = client.chat.completions.create(
model="n1-latest",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Search for Yutori on Google."},
{"type": "image_url", "image_url": {"url": "data:image/webp;base64,..."}}
]
}
]
)
# Response contains reasoning in content + actions in tool_calls
message = response.choices[0].message
print(message.content) # "I can see the Google homepage. I'll click on the search bar."
print(message.tool_calls) # [{"function": {"name": "left_click", "arguments": '{"coordinates": [640, 400]}'}}]
```
**n1 actions:** `left_click`, `double_click`, `triple_click`, `right_click`, `scroll`, `type`, `key_press`, `hover`, `drag`, `wait`, `goto_url`, `go_back`, `refresh`. Coordinates are in 1000x1000 space (must be converted to absolute). Custom tools can be added via the `tools` parameter.
**Screenshot requirements:** Browser content only (no OS chrome). Recommended resolution: 1280x800 (WXGA). Prefer WebP format.
**Pricing:** $0.75/M input tokens, $3/M output tokens.
---
### Browsing API
**Create a task:** `POST /v1/browsing/tasks`
```bash
curl -X POST https://api.yutori.com/v1/browsing/tasks \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"task": "Give me a list of all employees of Yutori.",
"start_url": "https://yutori.com"
}'
```
```python
import requests
response = requests.post(
"https://api.yutori.com/v1/browsing/tasks",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"task": "Give me a list of all employees of Yutori.",
"start_url": "https://yutori.com",
"max_steps": 75, # Optional (1-100, default 25)
"output_schema": {...}, # Optional JSON schema for structured output
"webhook_url": "https://...", # Optional completion notification
"webhook_format": "scout", # Optional: "scout", "slack", "zapier"
}
)
task_id = response.json()["task_id"]
```
**Get task status:** `GET /v1/browsing/tasks/{task_id}`
```python
result = requests.get(
f"https://api.yutori.com/v1/browsing/tasks/{task_id}",
headers={"X-API-Key": "YOUR_API_KEY"},
).json()
# result["status"]: "queued" | "running" | "succeeded" | "failed"
```
**Get task trajectory:** `GET /v1/browsing/tasks/{task_id}/trajectory` — returns screenshots and actions for each step.
**Agent options:** `navigator-n1-latest` (default, $0.015/step), `claude-sonnet-4-5-computer-use-2025-01-24` ($0.10/step). Set `require_auth: true` for login flows.
---
### Research API
**Create a task:** `POST /v1/research/tasks`
```python
response = requests.post(
"https://api.yutori.com/v1/research/tasks",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"query": "What are the latest developments in quantum computing?",
"user_timezone": "America/Los_Angeles", # Optional
"user_location": "San Francisco, CA", # Optional
"output_schema": {...}, # Optional JSON schema
"webhook_url": "https://...", # Optional
}
)
task_id = response.json()["task_id"]
```
**Get task result:** `GET /v1/research/tasks/{task_id}`
```python
result = requests.get(
f"https://api.yutori.com/v1/research/tasks/{task_id}",
headers={"X-API-Key": "YOUR_API_KEY"},
).json()
# result["status"]: "queued" | "running" | "succeeded" | "failed"
```
**Pricing:** $0.35 per research task. Uses 100+ MCP tools for comprehensive research.
---
### Scouting API
**Create a scout:** `POST /v1/scouting/tasks`
```python
response = requests.post(
"https://api.yutori.com/v1/scouting/tasks",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"query": "Tell me about the latest news about Yutori",
"output_interval": 86400, # Seconds between runs (min 1800, default 86400)
"user_timezone": "America/Los_Angeles", # Optional
"output_schema": {...}, # Optional JSON schema
"webhook_url": "https://...", # Optional
"webhook_format": "scout", # "scout", "slack", "zapier"
"skip_email": False, # Optional
}
)
scout_id = response.json()["id"]
```
**Other endpoints:**
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/v1/scouting/tasks` | List scouts (params: `page_size`, `status`) |
| `GET` | `/v1/scouting/tasks/{id}` | Get scout details |
| `PATCH` | `/v1/scouting/tasks/{id}` | Update scout fields |
| `POST` | `/v1/scouting/tasks/{id}/pause` | Pause a scout |
| `POST` | `/v1/scouting/tasks/{id}/restart` | Resume a scout |
| `POST` | `/v1/scouting/tasks/{id}/complete` | Archive a scout |
| `DELETE` | `/v1/scouting/tasks/{id}` | Delete a scout |
| `GET` | `/v1/scouting/tasks/{id}/updates` | Get scout updates (params: `limit`, `cursor`) |
**Pricing:** $0.35 per scout-run.
---
## Python SDK
Install: `pip install yutori`
```python
from yutori import YutoriClient
client = YutoriClient(api_key="yt-...") # Or set YUTORI_API_KEY env var, or run `yutori auth login`
```
**Auth resolution order:** explicit `api_key` param > `YUTORI_API_KEY` env var > `~/.yutori/config.json` (from CLI login).
### SDK Methods
**n1 (browser control):**
```python
response = client.chat.completions.create(
model="n1-latest",
messages=[{"role": "user", "content": [{"type": "text", "text": "..."}, {"type": "image_url", "image_url": {"url": "..."}}]}]
)
```
**Browsing:**
```python
task = client.browsing.create(task="...", start_url="https://...", max_steps=75, output_schema={...})
result = client.browsing.get(task["task_id"])
```
**Research:**
```python
task = client.research.create(query="...", output_schema={...})
result = client.research.get(task["task_id"])
```
**Scouting:**
```python
scout = client.scouts.create(query="...", output_interval=86400)
scouts = client.scouts.list(limit=20, status="active")
detail = client.scouts.get(scout_id)
updates = client.scouts.get_updates(scout_id, limit=10)
client.scouts.update(scout_id, status="paused")
client.scouts.delete(scout_id)
```
**Async client:** `AsyncYutoriClient` has the same interface — all methods are coroutines.
```python
from yutori import AsyncYutoriClient
async with AsyncYutoriClient() as client:
task = await client.browsing.create(task="...", start_url="https://...")
```
**Error handling:**
```python
from yutori import APIError, AuthenticationError
try:
client.get_usage()
except AuthenticationError as e:
print(f"Invalid API key: {e}")
except APIError as e:
print(f"API error (status {e.status_code}): {e.message}")
```
**CLI:**
```bash
yutori auth login # Authenticate via browser
yutori browse run "task" "url" # Start browsing task
yutori browse get TASK_ID # Get browsing result
yutori research run "query" # Start research task
yutori research get TASK_ID # Get research result
yutori scouts create -q "query" # Create a scout
yutori scouts list # List scouts
yutori scouts get SCOUT_ID # Get scout details
yutori scouts delete SCOUT_ID # Delete a scout
```
Full SDK reference: [github.com/yutori-ai/yutori-sdk-python/blob/main/api.md](https://github.com/yutori-ai/yutori-sdk-python/blob/main/api.md)
---
## MCP Server
Install: `pip install yutori-mcp`
The [Yutori MCP server](https://github.com/yutori-ai/yutori-mcp) provides 10 tools for AI assistants (Claude, Cursor, VS Code, ChatGPT, Codex, etc.) to interact with the Yutori API.
### Available Tools
**Scout tools:** `list_scouts`, `get_scout_detail`, `create_scout`, `edit_scout`, `delete_scout`, `get_scout_updates`
**Research tools:** `run_research_task`, `get_research_task_result`
**Browsing tools:** `run_browsing_task`, `get_browsing_task_result`
All tools accept JSON parameters and return formatted text responses. Key parameters:
- `create_scout`: `query` (required), `output_interval`, `webhook_url`, `output_fields`, `user_timezone`, `skip_email`
- `run_research_task`: `query` (required), `user_timezone`, `output_fields`, `webhook_url`
- `run_browsing_task`: `task` (required), `start_url` (required), `max_steps`, `output_fields`, `webhook_url`
Full MCP tools reference: [github.com/yutori-ai/yutori-mcp/blob/main/TOOLS.md](https://github.com/yutori-ai/yutori-mcp/blob/main/TOOLS.md)