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

# 爬取

> 递归爬取网站并获取每个页面的内容

爬取会将一个 URL 提交给 Firecrawl，并递归发现和抓取所有可到达的子页面。它会自动处理 sitemap、JavaScript 渲染和速率限制，并为每个页面返回干净的 Markdown 或结构化数据。

* 通过 sitemap 和递归链接遍历发现页面
* 支持路径过滤、深度限制以及对子域名/外部链接的控制
* 通过轮询、WebSocket 或 webhook 返回结果

<Card title="在 Playground 中试用" icon="play" href="https://www.firecrawl.dev/playground?endpoint=crawl">
  在交互式 Playground 中测试爬取功能——无需代码。
</Card>

<div id="installation">
  ## 安装
</div>

<CodeGroup>
  ```python Python theme={null}
  # 使用 pip 安装 firecrawl-py

  from firecrawl import Firecrawl

  firecrawl = Firecrawl(
    # 无需 API 密钥即可开始使用 — 添加一个以获得更高的限流额度：
    # api_key="fc-YOUR-API-KEY",
  )
  ```

  ```js Node theme={null}
  // 使用 npm 安装 firecrawl

  import { Firecrawl } from 'firecrawl';

  const firecrawl = new Firecrawl({
    // 无需 API 密钥即可开始使用 — 添加一个以获得更高的限流额度：
    // apiKey: "fc-YOUR-API-KEY",
  });
  ```

  ```bash CLI theme={null}
  # 使用 npm 全局安装
  npm install -g firecrawl

  # 身份验证(一次性设置)
  firecrawl login
  ```
</CodeGroup>

<div id="basic-usage">
  ## 基本用法
</div>

调用 `POST /v2/crawl` 并提供起始 URL，即可提交爬取任务。该端点会返回一个任务 ID，你可以用它轮询结果。

<CodeGroup>
  ```python Python theme={null}
  from firecrawl import Firecrawl

  firecrawl = Firecrawl(api_key="fc-你的API密钥")

  docs = firecrawl.crawl(url="https://docs.firecrawl.dev", limit=10)
  print(docs)
  ```

  ```js Node theme={null}
  import { Firecrawl } from 'firecrawl';

  const firecrawl = new Firecrawl({ apiKey: "fc-你的API密钥" });

  const docs = await firecrawl.crawl('https://docs.firecrawl.dev', { limit: 10 });
  console.log(docs);
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.firecrawl.dev/v2/crawl" \
    -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://docs.firecrawl.dev",
      "limit": 10
    }'
  ```

  ```bash CLI theme={null}
  # 启动爬取任务(返回任务 ID)
  firecrawl crawl https://firecrawl.dev

  # 等待完成并显示进度
  firecrawl crawl https://firecrawl.dev --wait --progress --limit 100
  ```
</CodeGroup>

<Info>
  每爬取 1 个页面会消耗 1 个额度。爬取的默认 `limit` 为 10,000 个页面。在开始之前，爬取端点会检查你的剩余额度是否足以覆盖 `limit`；如果不足，则会返回 **402 (需要付款) ** 错误。你可以设置更低的 `limit` 来匹配计划的爬取规模 (例如将 `limit` 设为 100) ，以避免这种情况。某些选项会额外消耗额度：JSON 模式每个页面额外消耗 4 个额度，增强代理每个页面额外消耗 4 个额度，PDF 解析每个 PDF 页面额外消耗 1 个额度。
</Info>

<div id="scrape-options">
  ### Scrape 选项
</div>

[Scrape 端点](/zh/api-reference/endpoint/scrape)的所有选项都可通过 `scrapeOptions` (JS) / `scrape_options` (Python) 在 crawl 中使用。它们将应用于爬虫抓取的每个页面，包括 formats、代理、缓存、actions、location 和 tags。

<CodeGroup>
  ```python Python theme={null}
  from firecrawl import Firecrawl

  firecrawl = Firecrawl(api_key='fc-YOUR_API_KEY')

  # 使用 scrape 选项进行爬取
  response = firecrawl.crawl('https://example.com',
      limit=100,
      scrape_options={
          'formats': [
              'markdown',
              { 'type': 'json', 'schema': { 'type': 'object', 'properties': { 'title': { 'type': 'string' } } } }
          ],
          'proxy': 'auto',
          'max_age': 600000,
          'only_main_content': True
      }
  )
  ```

  ```js Node theme={null}
  import { Firecrawl } from 'firecrawl';

  const firecrawl = new Firecrawl({ apiKey: 'fc-YOUR_API_KEY' });

  // 使用 scrape 选项进行爬取
  const crawlResponse = await firecrawl.crawl('https://example.com', {
    limit: 100,
    scrapeOptions: {
      formats: [
        'markdown',
        {
          type: 'json',
          schema: { type: 'object', properties: { title: { type: 'string' } } },
        },
      ],
      proxy: 'auto',
      maxAge: 600000,
      onlyMainContent: true,
    },
  });
  ```
</CodeGroup>

<div id="checking-crawl-status">
  ## 检查爬取状态
</div>

使用任务 ID 轮询爬取状态并获取结果。

<CodeGroup>
  ```python Python theme={null}
  status = firecrawl.get_crawl_status("<crawl-id>")
  print(status)
  ```

  ```js Node theme={null}
  const status = await firecrawl.getCrawlStatus("<crawl-id>");
  console.log(status);
  ```

  ```bash cURL theme={null}
  # 启动爬取后，使用 jobId 轮询状态
  curl -s -X GET "https://api.firecrawl.dev/v2/crawl/<jobId>" \
    -H "Authorization: Bearer $FIRECRAWL_API_KEY"
  ```

  ```bash CLI theme={null}
  # 使用作业 ID 检查爬取状态
  firecrawl crawl <job-id>
  ```
</CodeGroup>

<Note>
  任务结果在完成后 24 小时内可通过 API 获取。此后，你仍可以在[活动日志](https://www.firecrawl.dev/app/logs)中查看你的爬取历史和结果。
</Note>

<Note>
  爬取结果中的 `data` 数组里包含的是 Firecrawl 成功抓取的页面，即使目标站点返回了 404 等 HTTP 错误。`metadata.statusCode` 字段显示的是目标站点返回的 HTTP 状态码。若要获取 Firecrawl 本身未能成功抓取的页面 (例如网络错误、超时或被 robots.txt 拦截) ，请使用专门的 [Get Crawl Errors](/zh/api-reference/endpoint/crawl-get-errors) 端点 (`GET /crawl/{id}/errors`) 。
</Note>

<div id="response-handling">
  ### 响应处理
</div>

响应会根据爬取任务的状态而有所不同。对于未完成的任务或超过 10MB 的大型响应，会返回一个 `next` URL 参数。你需要请求该 URL 以获取后续的每 10MB 数据。如果没有 `next` 参数，则表示爬取数据已结束。

<Info>
  仅在直接调用 API 时，`skip` 和 `next` 参数才生效。
  如果你使用 SDK，我们会代为处理，并一次性返回全部结果。
</Info>

<CodeGroup>
  ```json 抓取中 theme={null}
  {
    "status": "抓取中",
    "total": 36,
    "completed": 10,
    "creditsUsed": 10,
    "expiresAt": "2024-00-00T00:00:00.000Z",
    "next": "https://api.firecrawl.dev/v2/crawl/123-456-789?skip=10",
    "data": [
      {
        "markdown": "[Firecrawl 文档首页![浅色标志](https://mintlify.s3-us-west-1.amazonaws.com/firecrawl/logo/light.svg)!...",
        "html": "<!DOCTYPE html><html lang=\"en\" class=\"js-focus-visible lg:[--scroll-mt:9.5rem]\" data-js-focus-visible=\"\">...",
        "metadata": {
          "title": "使用 Groq Llama 3 构建“网站聊天” | Firecrawl",
          "language": "en",
          "sourceURL": "https://docs.firecrawl.dev/learn/rag-llama3",
          "description": "了解如何使用 Firecrawl、Groq Llama 3 和 Langchain 构建一个“网站聊天”机器人。",
          "ogLocaleAlternate": [],
          "statusCode": 200
        }
      },
      ...
    ]
  }
  ```

  ```json 已完成 theme={null}
  {
    "status": "completed",
    "total": 36,
    "completed": 36,
    "creditsUsed": 36,
    "expiresAt": "2024-00-00T00:00:00.000Z",
    "next": "https://api.firecrawl.dev/v2/crawl/123-456-789?skip=26",
    "data": [
      {
        "markdown": "[Firecrawl 文档首页![浅色 logo](https://mintlify.s3-us-west-1.amazonaws.com/firecrawl/logo/light.svg)!...",
        "html": "<!DOCTYPE html><html lang=\"en\" class=\"js-focus-visible lg:[--scroll-mt:9.5rem]\" data-js-focus-visible=\"\">...",
        "metadata": {
          "title": "使用 Groq Llama 3 构建“网站聊天” | Firecrawl",
          "language": "en",
          "sourceURL": "https://docs.firecrawl.dev/learn/rag-llama3",
          "description": "了解如何使用 Firecrawl、Groq Llama 3 和 LangChain 构建一个“网站聊天”机器人。",
          "ogLocaleAlternate": [],
          "statusCode": 200
        }
      },
      ...
    ]
  }
  ```
</CodeGroup>

<div id="sdk-methods">
  ## SDK 方法
</div>

通过 SDK 使用 crawl 有两种方式。

<div id="crawl-and-wait">
  ### 抓取并等待
</div>

`crawl` 方法会等待爬取完成并返回完整响应。自动处理分页。适用于大多数场景，推荐使用。

<CodeGroup>
  ```python Python theme={null}
  from firecrawl import Firecrawl
  from firecrawl.types import ScrapeOptions

  firecrawl = Firecrawl(api_key="fc-YOUR_API_KEY")

  # 爬取网站：
  crawl_status = firecrawl.crawl(
    'https://firecrawl.dev', 
    limit=100, 
    scrape_options=ScrapeOptions(formats=['markdown', 'html']),
    poll_interval=30
  )
  print(crawl_status)
  ```

  ```js Node theme={null}
  import { Firecrawl } from 'firecrawl';

  const firecrawl = new Firecrawl({apiKey: "fc-YOUR_API_KEY"});

  const crawlResponse = await firecrawl.crawl('https://firecrawl.dev', {
    limit: 100,
    scrapeOptions: {
      formats: ['markdown', 'html'],
    }
  })

  console.log(crawlResponse)
  ```
</CodeGroup>

响应包括爬取状态及所有抓取到的数据：

<CodeGroup>
  ```bash Python theme={null}
  success=True
  status='completed'
  completed=100
  total=100
  creditsUsed=100
  expiresAt=datetime.datetime(2025, 4, 23, 19, 21, 17, tzinfo=TzInfo(UTC))
  next=None
  data=[
    Document(
      markdown='[第 7 天 - 发布周 III · 集成日（4 月 14 日至 20 日）](...',
      metadata={
        'title': '15 个 Python 网页爬取项目：从入门到进阶',
        ...
        'scrapeId': '97dcf796-c09b-43c9-b4f7-868a7a5af722',
        'sourceURL': 'https://www.firecrawl.dev/blog/python-web-scraping-projects',
        'url': 'https://www.firecrawl.dev/blog/python-web-scraping-projects',
        'statusCode': 200
      }
    ),
    ...
  ]
  ```

  ```js Node theme={null}
  {
    success: true,
    status: "completed",
    completed: 100,
    total: 100,
    creditsUsed: 100,
    expiresAt: "2025-04-23T19:28:45.000Z",
    data: [
      {
        markdown: "[Day 7 - Launch Week III.Integrations DayApril ...",
        html: `<!DOCTYPE html><html lang="en" class="light" style="color...`,
        metadata: [Object],
      },
      ...
    ]
  }
  ```
</CodeGroup>

<div id="start-and-check-later">
  ### 启动后稍后检查
</div>

`startCrawl` / `start_crawl` 方法会立即返回一个爬取 ID。随后你需要手动轮询状态。这适合长时间运行的爬取任务或自定义轮询逻辑。

<CodeGroup>
  ```python Python theme={null}
  from firecrawl import Firecrawl

  firecrawl = Firecrawl(api_key="fc-YOUR-API-KEY")

  job = firecrawl.start_crawl(url="https://docs.firecrawl.dev", limit=10)
  print(job)

  # 检查爬取任务的状态
  status = firecrawl.get_crawl_status(job.id)
  print(status)
  ```

  ```js Node theme={null}
  import { Firecrawl } from 'firecrawl';

  const firecrawl = new Firecrawl({ apiKey: "fc-YOUR-API-KEY" });

  const { id } = await firecrawl.startCrawl('https://docs.firecrawl.dev', { limit: 10 });
  console.log(id);

  // 检查抓取进度
  const status = await firecrawl.getCrawlStatus(id);
  console.log(status);

  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.firecrawl.dev/v2/crawl" \
    -H "Authorization: Bearer $FIRECRAWL_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://docs.firecrawl.dev",
      "limit": 10
    }'
  ```

  ```bash CLI theme={null}
  # 启动爬取(异步,立即返回作业 ID)
  firecrawl crawl https://firecrawl.dev --limit 100

  # 稍后检查状态
  firecrawl crawl <job-id>
  ```
</CodeGroup>

初始响应会返回任务 ID：

```json theme={null}
{
  "success": true,
  "id": "123-456-789",
  "url": "https://api.firecrawl.dev/v2/crawl/123-456-789"
}
```

<div id="real-time-results-with-websocket">
  ## 使用 WebSocket 获取实时结果
</div>

watcher 方法会在页面爬取过程中提供实时更新。启动爬取后，订阅事件即可进行即时数据处理。

<CodeGroup>
  ```python Python theme={null}
  import asyncio
  from firecrawl import AsyncFirecrawl

  async def main():
      firecrawl = AsyncFirecrawl(api_key="fc-YOUR-API-KEY")

      # 首先启动爬取
      started = await firecrawl.start_crawl("https://firecrawl.dev", limit=5)

      # 监听更新（快照）直到终止状态
      async for snapshot in firecrawl.watcher(started.id, kind="crawl", poll_interval=2, timeout=120):
          if snapshot.status == "completed":
              print("完成", snapshot.status)
              for doc in snapshot.data:
                  print("文档", doc.metadata.source_url if doc.metadata else None)
          elif snapshot.status == "failed":
              print("错误", snapshot.status)
          else:
              print("状态", snapshot.status, snapshot.completed, "/", snapshot.total)

  asyncio.run(main())
  ```

  ```js Node theme={null}
  import { Firecrawl } from 'firecrawl';

  const firecrawl = new Firecrawl({ apiKey: 'fc-YOUR-API-KEY' });

  // 启动一次爬取并开始监控
  const { id } = await firecrawl.startCrawl('https://mendable.ai', {
    excludePaths: ['blog/*'],
    limit: 5,
  });

  const watcher = firecrawl.watcher(id, { kind: 'crawl', pollInterval: 2, timeout: 120 });

  watcher.on('document', (doc) => {
    console.log('DOC', doc);
  });

  watcher.on('error', (err) => {
    console.error('ERR', err?.error || err);
  });

  watcher.on('done', (state) => {
    console.log('DONE', state.status);
  });

  // 开始监控（优先使用 WS，回退到 HTTP）
  await watcher.start();
  ```
</CodeGroup>

<div id="webhooks">
  ## Webhooks
</div>

你可以配置 webhook，在爬取过程中实时接收通知，从而在页面被抓取后立即进行处理，而无需等待整个爬取任务完成。

```bash cURL theme={null}
curl -X POST https://api.firecrawl.dev/v2/crawl \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -d '{
      "url": "https://docs.firecrawl.dev",
      "limit": 100,
      "webhook": {
        "url": "https://your-domain.com/webhook",
        "metadata": {
          "any_key": "any_value"
        },
        "events": ["started", "page", "completed"]
      }
    }'
```

<div id="event-types">
  ### 事件类型
</div>

| 事件                | 描述           |
| ----------------- | ------------ |
| `crawl.started`   | 在爬取开始时触发     |
| `crawl.page`      | 每个页面成功抓取后触发  |
| `crawl.completed` | 在爬取结束时触发     |
| `crawl.failed`    | 爬取过程中发生错误时触发 |

<div id="payload">
  ### 负载
</div>

```json theme={null}
{
  "success": true,
  "type": "crawl.page",
  "id": "crawl-job-id",
  "data": [...], // 'page' 事件的页面数据
  "metadata": {}, // Your custom metadata
  "error": null
}
```

<div id="verifying-webhook-signatures">
  ### 验证 webhook 签名
</div>

来自 Firecrawl 的每个 webhook 请求都会包含一个 `X-Firecrawl-Signature` 请求头，其中含有一个 HMAC-SHA256 签名。务必验证此签名，以确保 webhook 为真实请求且未被篡改。

1. 在账户设置中的 [Advanced (高级) 选项卡](https://www.firecrawl.dev/app/settings?tab=advanced) 获取你的 webhook 密钥 (secret)
2. 从 `X-Firecrawl-Signature` 请求头中提取签名
3. 使用该密钥对原始请求体计算 HMAC-SHA256
4. 使用时间安全函数 (timing-safe function) 将计算结果与签名请求头中的值进行比较

<Warning>
  在验证签名之前，切勿处理任何 webhook。`X-Firecrawl-Signature` 请求头中的签名格式为：`sha256=abc123def456...`
</Warning>

有关 JavaScript 和 Python 的完整实现示例，请参阅 [Webhook 安全文档](/zh/webhooks/security)。如需查看更全面的 webhook 文档，包括详细的事件负载、负载结构、高级配置和故障排查，请参阅 [Webhooks 文档](/zh/webhooks/overview)。

<div id="configuration-reference">
  ## 配置参考
</div>

提交爬取任务时可用的完整参数集：

| 参数                      | 类型         | 默认值         | 说明                                                                                                                                                                      |
| ----------------------- | ---------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url`                   | `string`   | (必填)        | 开始爬取的起始 URL                                                                                                                                                             |
| `limit`                 | `integer`  | `10000`     | 最大爬取页面数                                                                                                                                                                 |
| `maxDiscoveryDepth`     | `integer`  | (无)         | 基于链接发现跳数、相对于根 URL 的最大深度，而不是 URL 中 `/` 分段的数量。每当在某个页面上发现一个新 URL 时，其深度都会被设为比发现它的页面高 1。根站点和通过站点地图发现的页面，其发现深度为 0。处于最大深度的页面仍会被抓取，但不会继续跟踪其上的链接。                                |
| `includePaths`          | `string[]` | (无)         | 要包含的 URL 路径正则表达式模式。仅爬取匹配的路径。                                                                                                                                            |
| `excludePaths`          | `string[]` | (无)         | 要从爬取中排除的 URL 路径正则表达式模式                                                                                                                                                  |
| `regexOnFullURL`        | `boolean`  | `false`     | 让 `includePaths`/`excludePaths` 针对完整 URL (包括查询参数) 进行匹配，而不只是路径部分                                                                                                         |
| `crawlEntireDomain`     | `boolean`  | `false`     | 跟踪指向同级或上级 URL 的站内链接，而不只是子路径                                                                                                                                             |
| `allowSubdomains`       | `boolean`  | `false`     | 跟踪指向主域名下子域名的链接                                                                                                                                                          |
| `allowExternalLinks`    | `boolean`  | `false`     | 跟踪指向外部网站的链接                                                                                                                                                             |
| `sitemap`               | `string`   | `"include"` | 站点地图处理方式：`"include"` (默认) 、`"skip"` 或 `"only"`                                                                                                                          |
| `ignoreQueryParameters` | `boolean`  | `false`     | 避免因查询参数不同而对同一路径重复抓取                                                                                                                                                     |
| `ignoreRobotsTxt`       | `boolean`  | `false`     | 忽略网站的 robots.txt 规则。**仅限 Enterprise** — 请联系 [support@firecrawl.com](mailto:support@firecrawl.com) 启用。                                                                   |
| `robotsUserAgent`       | `string`   | (无)         | 用于评估 robots.txt 的自定义 User-Agent 字符串。设置后，将使用此 User-Agent 获取 robots.txt，并根据它而不是默认值来匹配规则。**仅限 Enterprise** — 请联系 [support@firecrawl.com](mailto:support@firecrawl.com) 启用。 |
| `delay`                 | `number`   | (无)         | 每次抓取之间的延迟时间 (秒) ，以遵守速率限制。设置此项会强制并发数为 1。                                                                                                                                 |
| `maxConcurrency`        | `integer`  | (无)         | 最大并发抓取数。默认使用你团队的并发限制。                                                                                                                                                   |
| `scrapeOptions`         | `object`   | (无)         | 应用于每个抓取页面的选项 (formats、代理、缓存、actions 等)                                                                                                                                  |
| `webhook`               | `object`   | (无)         | 用于实时通知的 webhook 配置                                                                                                                                                      |
| `prompt`                | `string`   | (无)         | 用于生成爬取选项的自然语言提示。显式设置的参数会覆盖自动生成的对应参数。                                                                                                                                    |

<div id="important-details">
  ## 重要说明
</div>

<Warning>
  默认情况下，crawl 会忽略不属于你提供的 URL 子路径的链接。例如，如果你抓取 `website.com/blogs/`，则不会返回 `website.com/other-parent/blog-1`。使用 `crawlEntireDomain` 参数可包含同级路径和父级路径。要在抓取 `website.com` 时一并抓取 `blog.website.com` 这类子域名，请使用 `allowSubdomains` 参数。
</Warning>

* **站点地图发现**：默认情况下，爬虫会包含网站的站点地图来发现 URL (`sitemap: "include"`) 。如果设置 `sitemap: "skip"`，则只会发现可通过根 URL 的 HTML 链接访问到的页面。像 PDF 这类资源，或列在站点地图中但未在 HTML 中直接链接的深层页面，都会被遗漏。为了获得最大覆盖率，建议保留默认设置。
* **Credit 消耗**：每抓取一个页面消耗 1 个 credit。JSON 模式每页额外消耗 4 个 credit，增强代理每页额外消耗 4 个 credit，PDF 解析则每个 PDF 页面消耗 1 个 credit。
* **结果过期时间**：任务结果在完成后的 24 小时内可通过 API 获取。此后，请在[活动日志](https://www.firecrawl.dev/app/logs)中查看结果。
* **抓取错误**：`data` 数组包含 Firecrawl 成功抓取的页面。使用 [Get Crawl Errors](/zh/api-reference/endpoint/crawl-get-errors) 端点可获取因网络错误、超时或被 robots.txt 阻止而失败的页面。
* **非确定性结果**：同一配置在多次运行之间的抓取结果可能会有所不同。页面会并发抓取，因此链接被发现的顺序取决于网络时序以及哪些页面先完成加载。这意味着在接近深度边界时，站点的不同分支可能会被探索到不同程度，尤其是在 `maxDiscoveryDepth` 值较高时。要获得更稳定的结果，请将 `maxConcurrency` 设置为 `1`，或者在站点拥有完整站点地图时使用 `sitemap: "only"`。

> 你是需要 Firecrawl API 密钥的 AI 代理吗？请参阅 [firecrawl.dev/agent-onboarding/SKILL.md](https://www.firecrawl.dev/agent-onboarding/SKILL.md) 了解自动化接入说明。
