> ## 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.

# Node

> 使用 Firecrawl Node SDK，从网站抓取、爬取并提取结构化数据。

从你的 Node.js 应用中抓取单个页面、爬取整个站点，并映射 URL。SDK 会处理分页、重试和异步任务轮询，让你能够专注于使用返回的数据。

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

使用 npm 安装 SDK：

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

import { Firecrawl } from 'firecrawl';

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

<div id="usage">
  ## 使用
</div>

1. 在 [firecrawl.dev](https://firecrawl.dev) 获取 API 密钥
2. 将该密钥设置为名为 `FIRECRAWL_API_KEY` 的环境变量，或作为参数传递给 `Firecrawl` 类。

<Note>
  **没有 API 密钥？** 你可以在不提供密钥的情况下构造 `Firecrawl`，并在免密钥的 Free 档位中使用 `scrape`、`search` 和 `interact` (按 IP 限流——请参见 [限流](/zh/rate-limits#keyless-no-api-key)) 。所有其他方法都需要密钥。
</Note>

以下是一个包含错误处理的 SDK 使用示例：

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

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

// 抓取网站内容
const scrapeResponse = await firecrawl.scrape('https://firecrawl.dev', {
  formats: ['markdown', 'html'],
});

console.log(scrapeResponse)

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

console.log(crawlResponse)
```

<div id="scraping-a-url">
  ### 抓取单个 URL
</div>

使用 `scrape` 方法抓取单个 URL，并返回结构化的页面数据。

```js Node theme={null}
// 抓取网站：
const scrapeResult = await firecrawl.scrape('firecrawl.dev', { formats: ['markdown', 'html'] });

console.log(scrapeResult)
```

<div id="parsing-uploaded-files">
  ### 解析上传的文件
</div>

当你想上传本地文件 (`html`、`pdf`、`docx`、`xlsx` 等) ，而不是通过 URL 抓取时，请使用 `parse`。
`parse` 不支持 `changeTracking`，也不支持仅适用于浏览器的选项，例如 `screenshot`、`branding`、`actions`、`waitFor`、`location` 和 `mobile`。

```js Node theme={null}
const parsed = await firecrawl.parse(
  {
    data: "<html><body><h1>Node Parse</h1></body></html>",
    filename: "upload.html",
    contentType: "text/html",
  },
  {
    formats: ["markdown"],
  },
);

console.log(parsed.markdown);
```

<div id="crawling-a-website">
  ### 爬取网站
</div>

使用 `crawl` 方法从单个 URL 开始爬取整个网站。你可以设置页面上限，将范围限制在特定域名内，并选择输出格式。请参见 [Pagination](#pagination) 了解自动和手动分页。

```js Node（Node.js） theme={null}
const job = await firecrawl.crawl('https://docs.firecrawl.dev', { limit: 5, pollInterval: 1, timeout: 120 });
console.log(job.status);
```

<div id="sitemap-only-crawl">
  ### 仅爬取 Sitemap
</div>

使用 `sitemap: "only"` 仅爬取 sitemap 中的 URL (起始 URL 始终会被包含，并且会跳过 HTML 链接发现过程) 。

```js Node theme={null}
const job = await firecrawl.crawl('https://docs.firecrawl.dev', {
  sitemap: 'only',
  limit: 25,
});
console.log(job.status, job.data.length);
```

<div id="start-a-crawl">
  ### 启动 爬取
</div>

使用 `startCrawl` 可启动一次爬取且无需等待其完成。该方法会返回一个任务 `ID`，供你稍后轮询。若需要阻塞等待直到完成，请改用 `crawl`。分页行为和限制详见 [Pagination](#pagination)。

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

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

使用 `checkCrawlStatus` 方法检查爬取任务当前是仍在运行、已完成还是已失败。传入 `startCrawl` 返回的任务 ID。

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

<div id="cancelling-a-crawl">
  ### 取消爬取
</div>

使用 `cancelCrawl` 方法取消正在运行中的爬取。传入由 `startCrawl` 返回的任务 ID。

```js Node theme={null}
const ok = await firecrawl.cancelCrawl("<crawl-id>");
console.log("已取消：", ok);
```

<div id="mapping-a-website">
  ### 网站映射
</div>

使用 `map` 方法可发现网站上的所有 URL。传入起始 URL，即可返回已发现页面的列表。

```js Node theme={null}
const res = await firecrawl.map('https://firecrawl.dev', { limit: 10 });
console.log(res.links);
```

<div id="crawling-a-website-with-websockets">
  ### 使用 WebSockets 爬取网站
</div>

使用 `crawlUrlAndWatch` 方法实时流式获取爬取结果。你会在每个页面完成爬取时立即收到结果，无需等待整个任务结束。

```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();
```

<div id="pagination">
  ### 分页
</div>

当有更多数据可用时，Firecrawl 的 /crawl 和 batch 端点会返回一个 `next` URL。Node SDK 默认会自动分页并汇总所有文档；在这种情况下，`next` 将为 `null`。你可以禁用自动分页或设置上限。

<div id="crawl">
  #### 抓取
</div>

使用 waiter 方法 `crawl` 以获得最简便的体验，或启动一个任务并手动逐页处理。

<div id="simple-crawl-auto-pagination-default">
  ##### 简单爬取 (自动分页，默认)
</div>

* 请参阅[网站爬取](#crawling-a-website)中的默认流程。

<div id="manual-crawl-with-pagination-control-single-page">
  ##### 手动抓取与分页控制 (单页)
</div>

* 先启动作业，然后将 `autoPaginate: false` 设置为禁用自动分页，逐页获取。

```js 节点 theme={null}
const crawlStart = await firecrawl.startCrawl('https://docs.firecrawl.dev', { limit: 5 });
const crawlJobId = crawlStart.id;

const crawlSingle = await firecrawl.getCrawlStatus(crawlJobId, { autoPaginate: false });
console.log('单页抓取：', crawlSingle.status, '文档数：', crawlSingle.data.length, '下一页：', crawlSingle.next);
```

<div id="manual-crawl-with-limits-auto-pagination-early-stop">
  ##### 设有限制的手动抓取 (自动分页 + 提前停止)
</div>

* 保持自动分页开启，但可通过 `maxPages`、`maxResults` 或 `maxWaitTime` 提前停止。

```js 节点 theme={null}
const crawlLimited = await firecrawl.getCrawlStatus(crawlJobId, {
  autoPaginate: true,
  maxPages: 2,
  maxResults: 50,
  maxWaitTime: 15,
});
console.log('受限爬取：', crawlLimited.status, '文档数：', crawlLimited.data.length, '下一页：', crawlLimited.next);
```

<div id="batch-scrape">
  #### 批量抓取
</div>

使用等待器方法 `batchScrape`，或手动启动作业并逐页处理。

<div id="simple-batch-scrape-auto-pagination-default">
  ##### 简单批量抓取 (自动分页，默认)
</div>

* 默认流程请参见[批量抓取](/zh/features/batch-scrape)。

<div id="manual-batch-scrape-with-pagination-control-single-page">
  ##### 手动批量抓取并控制分页 (单页)
</div>

* 启动作业，将 `autoPaginate: false` 以禁用自动分页，并按页逐一获取。

```js Node theme={null}
const batchStart = await firecrawl.startBatchScrape([
  'https://docs.firecrawl.dev',
  'https://firecrawl.dev',
], { options: { formats: ['markdown'] } });
const batchJobId = batchStart.id;

const batchSingle = await firecrawl.getBatchScrapeStatus(batchJobId, { autoPaginate: false });
console.log('批量单页：', batchSingle.status, '文档数：', batchSingle.data.length, '下一页：', batchSingle.next);
```

<div id="manual-batch-scrape-with-limits-auto-pagination-early-stop">
  ##### 手动批量抓取并设定限制 (自动分页 + 提前停止)
</div>

* 保持自动分页开启，但可通过 `maxPages`、`maxResults` 或 `maxWaitTime` 提前停止。

```js Node theme={null}
const batchLimited = await firecrawl.getBatchScrapeStatus(batchJobId, {
  autoPaginate: true,
  maxPages: 2,
  maxResults: 100,
  maxWaitTime: 20,
});
console.log('批处理受限：', batchLimited.status, '文档数：', batchLimited.data.length, '下一个：', batchLimited.next);
```

<div id="browser">
  ## 浏览器
</div>

在云端启动浏览器会话并远程执行代码。

<div id="create-a-session">
  ### 创建会话
</div>

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

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

const session = await firecrawl.browser({ ttl: 600 });
console.log(session.id);          // 会话 ID
console.log(session.cdpUrl);      // wss://cdp-proxy.firecrawl.dev/cdp/...
console.log(session.liveViewUrl); // https://liveview.firecrawl.dev/...
```

<div id="execute-code">
  ### 执行代码
</div>

```js Node theme={null}
const result = await firecrawl.browserExecute(session.id, {
  code: 'await page.goto("https://news.ycombinator.com")\ntitle = await page.title()\nprint(title)',
});
console.log(result.result); // "Hacker News"
```

使用 JavaScript，而不是 Python：

```js Node theme={null}
const result = await firecrawl.browserExecute(session.id, {
  code: 'await page.goto("https://example.com"); const t = await page.title(); console.log(t);',
  language: "node",
});
```

通过 agent-browser 执行 bash：

```js Node theme={null}
const result = await firecrawl.browserExecute(session.id, {
  code: "agent-browser open https://example.com && agent-browser snapshot",
  language: "bash",
});
```

<div id="profiles">
  ### 浏览器配置
</div>

保存浏览器状态 (cookies、localStorage 等) ，以便跨会话复用：

```js Node theme={null}
const session = await firecrawl.browser({
  ttl: 600,
  profile: {
    name: "my-profile",
    saveChanges: true,
  },
});
```

<div id="connect-via-cdp">
  ### 通过 CDP 连接
</div>

要获得对 Playwright 的完全控制能力，请使用 CDP URL 直接连接：

```js Node theme={null}
import { chromium } from "playwright";

const browser = await chromium.connectOverCDP(session.cdpUrl);
const context = browser.contexts()[0];
const page = context.pages()[0] || await context.newPage();

await page.goto("https://example.com");
console.log(await page.title());

await browser.close();
```

<div id="list-close-sessions">
  ### 查看并关闭会话
</div>

```js Node theme={null}
// 列出活跃会话
const { sessions } = await firecrawl.listBrowsers({ status: "active" });
for (const s of sessions) {
  console.log(s.id, s.status, s.createdAt);
}

// 关闭会话
await firecrawl.deleteBrowser(session.id);
```

<div id="scrape-bound-interactive-session">
  ### 绑定到抓取任务的交互式会话
</div>

使用抓取任务 ID，可在该次抓取回放后的页面上下文中继续交互：

* `interact(jobId, {...})` 会在绑定到抓取任务的浏览器会话中运行代码。
* 首次调用 `interact` 时，会基于抓取上下文自动初始化会话。
* 对同一任务 ID 再次调用 `interact` 时，会复用当前的浏览器状态。
* 完成后，可使用 `stopInteraction(jobId)` 停止交互式会话。

```js Node theme={null}
const doc = await firecrawl.scrape("https://example.com", {
  actions: [{ type: "click", selector: "a[href='/pricing']" }],
});

const scrapeJobId = doc.metadata?.scrapeId;
if (!scrapeJobId) throw new Error("Missing scrape job id");

const run = await firecrawl.interact(scrapeJobId, {
  code: "console.log(await page.url())",
  language: "node",
  timeout: 60,
});
console.log(run.stdout);

await firecrawl.stopInteraction(scrapeJobId);
```

<div id="error-handling">
  ## 错误处理
</div>

SDK 会针对 Firecrawl API 返回的任何错误抛出包含详细信息的异常。请像上面的示例所示，使用 `try/catch` 代码块包装调用。

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