> ## Documentation Index
> Fetch the complete documentation index at: https://docs.55-tech.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Browser Rendering

> 支持 JavaScript 渲染的抓取。返回 Cookie、截图，支持自定义 JS 执行。

## 概述

`/browser` 端点支持 JavaScript 渲染的抓取。与 `/fetch`（返回原始 HTTP 响应）不同，`/browser` 会等待动态内容加载并返回完全渲染的页面。

**何时使用 `/browser` 而非 `/fetch`：**

* 页面需要 JavaScript 才能加载内容（SPA、动态网站）
* 您需要所有 Cookie，包括客户端脚本设置的 Cookie
* 您想执行自定义 JavaScript 提取数据
* 您需要渲染页面的截图

响应格式与 `/fetch` 相同（`meta`、`raw`、`raw_json`），并额外包含 Cookie、截图和 JS 执行结果。

## 端点

```
GET https://scraping-api.55-tech.com/browser
```

与 `/fetch` 用法一致 — 所有参数通过请求头传递。

## 请求头

| Header              | Required | Default | Description                                                    |
| ------------------- | -------- | ------- | -------------------------------------------------------------- |
| `X-API-Key`         | 是        | —       | API 密钥                                                         |
| `X-Target-URL`      | 是        | —       | 要渲染的目标 URL                                                     |
| `X-Wait-Strategy`   | 否        | `load`  | `load`、`networkidle` 或 `selector`（[详情](#等待策略)）                 |
| `X-Wait-Selector`   | 否        | —       | 要等待的 CSS 选择器（配合 `selector` 策略）                                 |
| `X-Timeout`         | 否        | `30`    | 超时时间，秒（`/browser` 最大 300，`/browser/stream` 默认运行至断开连接，24小时安全上限） |
| `X-JS-Expression`   | 否        | —       | 页面就绪后执行的 JavaScript                                            |
| `X-Screenshot`      | 否        | `false` | 捕获截图（`1` 或 `true`）                                             |
| `X-Expect-Selector` | 否        | —       | 必须存在的 CSS 选择器 — 缺失时在不同节点重试                                     |
| `X-Expect-Contains` | 否        | —       | 必须存在于内容中的子字符串 — 缺失时重试                                          |
| `X-Proxy`           | 否        | —       | 通过代理路由（`http://` 或 `socks5://`）                                |
| `X-Steps`           | 否        | —       | 浏览器操作的 JSON 数组（[详情](#steps)）                                   |
| `X-Block-Resources` | 否        | —       | 逗号分隔的阻止资源类型：`image,font,stylesheet,media`。默认不阻止                |
| `X-Geo`             | 否        | —       | 节点国家过滤器（如 `US`、`DE,AT`）                                        |
| `X-Agent`           | 否        | —       | 固定到特定节点（如 `de1`、`us3`）                                         |
| `Cookie`            | 否        | —       | 注入 Cookie（`name=value; name2=value2`）                          |
| `X-Cookies`         | 否        | —       | Cookie JSON 数组，用于完整控制（[格式](#cookies)）                          |

### 等待策略

| Strategy      | Description                      |
| ------------- | -------------------------------- |
| `load`        | 等待 `DOMContentLoaded` 事件（最快）     |
| `networkidle` | 等待直到不超过 2 个网络连接持续 500ms（最适合 SPA） |
| `selector`    | 等待 `X-Wait-Selector` 出现在 DOM 中   |

### Cookies

**简单 Cookie** — 使用标准 `Cookie` 请求头：

```
Cookie: session=abc123; token=xyz
```

**完整 Cookie 对象** — 使用 `X-Cookies` 请求头，需要域名、路径等控制时：

```
X-Cookies: [{"name":"session","value":"abc","domain":".example.com","secure":true}]
```

### Steps

页面加载后执行顺序浏览器操作 — 登录流程、多页导航、表单填写。

通过 `X-Steps` 请求头传递 JSON 数组：

```
X-Steps: [{"action":"type","selector":"#email","value":"user@example.com"},{"action":"click","selector":"#submit"},{"action":"waitNavigation"}]
```

**可用操作：**

| Action           | Params                | Description         |
| ---------------- | --------------------- | ------------------- |
| `navigate`       | `url`                 | 导航到新 URL            |
| `click`          | `selector`            | 点击元素（模拟人类鼠标移动）      |
| `type`           | `selector`, `value`   | 在输入框中输入文本           |
| `wait`           | `selector`, `timeout` | 等待元素出现              |
| `waitNavigation` | `waitUntil`           | 等待页面导航完成            |
| `scroll`         | `selector` 或 `x`, `y` | 滚动到元素或按像素滚动         |
| `press`          | `key`                 | 按键盘键（`Enter`、`Tab`） |
| `evaluate`       | `expression`          | 执行 JavaScript       |
| `screenshot`     | `fullPage`            | 截图                  |
| `sleep`          | `ms`                  | 等待固定毫秒数             |

每步在前一步完成后执行。添加 `"continueOnError": true` 可在失败时继续。

适用于 `/browser`（步骤完成后捕获）和 `/browser/stream`（步骤期间流式传输，结果以 `step_ok` / `step_error` 事件到达）。

### 资源阻止

```
X-Block-Resources: image,font,stylesheet
```

阻止图片和字体可以将渲染时间减少 50% 以上。

## 响应

```json theme={null}
{
  "meta": {
    "status": 200,
    "final_url": "https://example.com/",
    "http_version": "",
    "elapsed_ms": 3200,
    "blocked": false,
    "headers": { "content-type": "text/html; charset=utf-8" },
    "agent": { "id": "scraping-de5" },
    "bytes": 45210
  },
  "raw": "<!DOCTYPE html><html>...</html>",
  "raw_json": null,
  "cookies": [
    {
      "name": "session_id",
      "value": "a1b2c3...",
      "domain": ".example.com",
      "path": "/",
      "secure": true,
      "httpOnly": true,
      "sameSite": "Lax",
      "expires": 1735689600
    }
  ],
  "screenshot": null,
  "js_result": null
}
```

| Field        | Description                             |
| ------------ | --------------------------------------- |
| `meta`       | 与 `/fetch` 相同 — 状态码、最终 URL、响应头、耗时、节点 ID |
| `raw`        | 渲染后的页面文本。如果是有效 JSON 则为 `null`           |
| `raw_json`   | 解析后的 JSON 对象，否则为 `null`                 |
| `cookies`    | 渲染期间设置的所有 Cookie，包括 `httpOnly`          |
| `screenshot` | 全页 Base64 PNG（未请求时为 `null`）             |
| `js_result`  | `X-JS-Expression` 的返回值（未提供时为 `null`）    |

### 响应验证

使用 `X-Expect-Selector` 和 `X-Expect-Contains` 验证内容。验证失败时 API 自动在不同节点重试。

## 示例

### 渲染 JavaScript 页面

```bash theme={null}
curl -H "X-API-Key: YOUR_API_KEY" \
  -H "X-Target-URL: https://example.com" \
  -H "X-Wait-Strategy: networkidle" \
  https://scraping-api.55-tech.com/browser
```

### 等待特定内容

```bash theme={null}
curl -H "X-API-Key: YOUR_API_KEY" \
  -H "X-Target-URL: https://example.com/dashboard" \
  -H "X-Wait-Strategy: selector" \
  -H "X-Wait-Selector: #data-table" \
  -H "X-Timeout: 45" \
  https://scraping-api.55-tech.com/browser
```

### 使用 JavaScript 提取数据

```bash theme={null}
curl -H "X-API-Key: YOUR_API_KEY" \
  -H "X-Target-URL: https://example.com" \
  -H "X-Wait-Strategy: networkidle" \
  -H "X-JS-Expression: JSON.stringify({title: document.title})" \
  https://scraping-api.55-tech.com/browser
```

### 截图

```bash theme={null}
curl -H "X-API-Key: YOUR_API_KEY" \
  -H "X-Target-URL: https://example.com" \
  -H "X-Screenshot: 1" \
  -H "X-Block-Resources: image,font" \
  https://scraping-api.55-tech.com/browser
```

### 带 Cookie

```bash theme={null}
curl -H "X-API-Key: YOUR_API_KEY" \
  -H "X-Target-URL: https://example.com" \
  -H "Cookie: session=abc123; token=xyz" \
  -H "X-Wait-Strategy: networkidle" \
  https://scraping-api.55-tech.com/browser
```

### Python

```python theme={null}
import requests

resp = requests.get("https://scraping-api.55-tech.com/browser", headers={
    "X-API-Key": "YOUR_API_KEY",
    "X-Target-URL": "https://example.com",
    "X-Wait-Strategy": "networkidle",
    "X-JS-Expression": "document.title",
    "X-Block-Resources": "image,font",
})

data = resp.json()
print(data["meta"]["status"])       # 200
print(data["raw"][:200])            # 渲染后的 HTML
print(data["js_result"])            # "Example Domain"

for c in data["cookies"]:
    print(f"{c['name']}={c['value']} (httpOnly={c['httpOnly']})")
```

***

## Browser Stream（SSE）

对于长时间的实时会话，使用 `/browser/stream`。浏览器保持打开状态，通过 SSE 实时流式传输事件。

仅捕获数据请求（XHR/Fetch API 调用）— 完整 HTML 页面和 JavaScript 包会被自动过滤。默认不阻止任何资源，确保页面和组件正常加载。默认等待策略为 `networkidle`。所有数据通过 gzip 压缩传输。

**使用场景：**

* 捕获页面接收的 WebSocket 帧（实时数据流）
* 监控页面发出的 XHR/Fetch API 调用（实际数据端点）
* 监视 DOM 元素变化（价格更新、内容变化）

### 端点

```
GET https://scraping-api.55-tech.com/browser/stream
```

### 请求头

与 `/browser` 相同，另加：

| Header             | Default              | Description         |
| ------------------ | -------------------- | ------------------- |
| `X-Capture`        | `network,ws,console` | 逗号分隔的事件类型           |
| `X-DOM-Selector`   | —                    | 监视 DOM 变化的 CSS 选择器  |
| `X-Network-Filter` | —                    | 网络 URL 正则过滤器        |
| `X-WS-Filter`      | —                    | WebSocket URL 正则过滤器 |
| `X-JS-After-Load`  | —                    | 页面加载后执行的 JavaScript |

### SSE 事件

| Event        | Description            |
| ------------ | ---------------------- |
| `connected`  | 浏览器已加载，开始流式传输          |
| `network`    | 捕获的 HTTP 响应（XHR/Fetch） |
| `ws_open`    | 页面打开了 WebSocket 连接     |
| `ws_message` | 页面接收到 WebSocket 帧      |
| `ws_close`   | 页面 WebSocket 已关闭       |
| `dom`        | 监视选择器的 DOM 变化          |
| `console`    | 控制台输出                  |
| `error`      | 错误，流结束                 |
| `done`       | 会话结束（超时或客户端断开连接）       |

### 示例：捕获页面 WebSocket 数据

<CodeGroup>
  ```bash 请求 theme={null}
  curl -N -H "X-API-Key: YOUR_API_KEY" \
    -H "X-Target-URL: https://example.com/live" \
    -H "X-Capture: ws" \
    https://scraping-api.55-tech.com/browser/stream
  ```

  ```text SSE 响应流 theme={null}
  event: connected
  data: {"type":"connected","url":"https://example.com/live","agent_id":"scraping-us5","timestamp":1775511253069}

  event: ws_open
  data: {"type":"ws_open","url":"wss://feed.example.com/ws","ws_id":"req-1234","timestamp":1775511254100}

  event: ws_message
  data: {"type":"ws_message","data":"{\"price\":1.95,\"event\":\"update\"}","ws_id":"req-1234","timestamp":1775511254500}

  event: ws_message
  data: {"type":"ws_message","data":"{\"price\":2.10,\"event\":\"update\"}","ws_id":"req-1234","timestamp":1775511255200}
  ```
</CodeGroup>

<ResponseExample>
  ```json connected theme={null}
  {
    "type": "connected",
    "url": "https://example.com/live",
    "status": 200,
    "agent_id": "scraping-us5",
    "timestamp": 1775511253069
  }
  ```

  ```json ws_message theme={null}
  {
    "type": "ws_message",
    "data": "{\"price\":1.95,\"market\":\"moneyline\"}",
    "ws_id": "req-1234",
    "timestamp": 1775511254500
  }
  ```

  ```json network theme={null}
  {
    "type": "network",
    "url": "https://api.example.com/v1/odds",
    "method": "GET",
    "status": 200,
    "data": "{\"odds\":[{\"home\":1.95,\"away\":2.10}]}",
    "content_type": "application/json",
    "timestamp": 1775511255000
  }
  ```
</ResponseExample>

<Note>
  SSE 流持续运行直到断开连接。每个事件格式为 `event: type\ndata: json\n\n`。使用 `curl -N`（无缓冲）实时查看事件。
</Note>

### Python

```python theme={null}
import requests
import json

resp = requests.get("https://scraping-api.55-tech.com/browser/stream", headers={
    "X-API-Key": "YOUR_API_KEY",
    "X-Target-URL": "https://example.com/live",
    "X-Capture": "ws",
}, stream=True)

for line in resp.iter_lines():
    if line.startswith(b"data: "):
        event = json.loads(line[6:])
        if event["type"] == "ws_message":
            print(event["data"])
```

## 后续步骤

<Columns cols={2}>
  <Card title="HTTP Fetch" icon="bolt" href="/zh/scraping-api/quickstart">
    对于不需要 JavaScript 渲染的页面，使用更快的 `/fetch` 端点。
  </Card>

  <Card title="Error handling" icon="triangle-exclamation" href="/zh/scraping-api/errors">
    状态码、封锁检测和重试策略。
  </Card>
</Columns>
