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

# TypeScript SDK

> 面向 Decodo API 的官方 TypeScript SDK，提供强类型目标、IDE 自动补全，以及同步、异步和批量抓取方法。

> [!NOTE]
>
> 最新的安装说明、示例和源代码请查看 [TypeScript SDK GitHub 仓库](https://github.com/Decodo/sdk-ts)。

使用官方 Decodo TypeScript SDK，为搜索引擎、电商平台、社交媒体、AI 工具等构建强类型的抓取工作流。

* 完整类型化的目标和参数，支持 IDE 自动补全
* 同步、异步和批量抓取方法
* 通过 Web Data API 提供网页搜索、站点地图和爬取功能
* 原生支持 `fetch`；需要 Node.js 18 或更高版本
* 类型化的错误层级，让集成更安全

## 什么是 Decodo TypeScript SDK？

Decodo TypeScript SDK 为 Google、Amazon、TikTok、YouTube、ChatGPT、Perplexity 等 Decodo 目标提供类型化接口。您无需手动构造 HTTP 请求和校验载荷，而是直接在编辑器中使用完整类型化的方法和特定目标的参数。

## 为什么使用该 SDK？

* **强类型与自动补全**：目标参数完整类型化，带来更好的编辑器支持和更少的错误。
* **统一的抓取接口**：通过同一个 SDK 使用搜索引擎、电商平台、社交媒体和 AI 工具。
* **异步与批量工作流**：创建抓取任务、轮询任务状态，并大规模处理批量请求。
* **类型化错误**：安全地处理身份验证、参数校验、超时和速率限制等失败情况。
* **配置极简**：使用原生 `fetch`，无需额外的 HTTP 客户端。

## 要求

* Node.js 18 或更高版本，以支持原生 `fetch`
* 推荐使用 TypeScript 5.0 或更高版本，以获得最佳类型推断

## 安装

```bash theme={null}
npm install --save @decodo/sdk-ts
```

## 快速开始

创建一个新项目：

```bash theme={null}
mkdir scrape-with-decodo
cd scrape-with-decodo
npm init -y
npm install --save @decodo/sdk-ts
touch main.js
```

`npm init -y` 创建的是 CommonJS 包，因此使用 `import` 的文件会失败并报 `SyntaxError: Cannot use import statement outside a module`。请先将该包切换为 ES 模块：

```bash theme={null}
node -e "let p=require('./package.json'); p.type='module'; require('fs').writeFileSync('./package.json', JSON.stringify(p, null, 2))"
```

在 [**Decodo 控制面板**](https://dashboard.decodo.com/web-data/playground)中，从您的 Web Data API 订阅复制 Web Data API 密钥。请将其存储在环境变量中，避免写入源代码：

```bash theme={null}
export DECODO_API_KEY=your_api_key
```

> [!NOTE]
>
> 较旧的计划只有基本身份验证令牌。请将其作为 `token` 传入，而不是 `apiKey`——详见下文的"配置"一节。

然后创建 `main.js` 并初始化客户端：

```javascript theme={null}
// main.js
import { DecodoClient, Target } from '@decodo/sdk-ts';

const client = new DecodoClient({
  webScrapingApi: {
    apiKey: process.env.DECODO_API_KEY,
  },
});

const result = await client.webScrapingApi.scrape({
  target: Target.GoogleSearch,
  query: 'coffee shops',
  geo: 'United States',
  parse: true,
});

console.log(JSON.stringify(result, null, 2));
```

运行脚本：

```bash theme={null}
node main.js
```

> [!WARNING]
>
> 请保持该文件为纯 JavaScript。诸如 `process.env.DECODO_API_KEY!` 中的非空断言等 TypeScript 专有语法，在 `node main.js` 下会报 `SyntaxError: Unexpected token '!'`。该写法只应出现在您会编译或通过 TypeScript 加载器运行的 `.ts` 文件中。

## 配置

```typescript theme={null}
const client = new DecodoClient({
  webScrapingApi: {
    apiKey: '<api_key>',
  },
  timeoutMs: 120_000, // optional, request timeout in ms (default: 180000)
});
```

请传入 `apiKey` 或 `token` 之一，切勿同时传入：

```typescript theme={null}
// Basic authentication token (older plans)
const client = new DecodoClient({
  webScrapingApi: {
    token: '<basic_auth_token>',
  },
});
```

| 参数 | 说明 |
| - | - |
| `apiKey` | 控制面板中订阅所对应的 Web Data API 密钥。**推荐** |
| `token` | 较旧计划的基本身份验证令牌。请用它替代 `apiKey` |
| `baseUrl` | 覆盖 API 的基础 URL。必须是合法的 URL |
| `timeoutMs` | 请求超时毫秒数（默认：180000） |

> [!NOTE]
>
> 同时设置两者会抛出 `webScrapingApi accepts either token or apiKey, not both. Provide only one.`；两者都不设置会抛出 `webScrapingApi requires apiKey or token in DecodoConfig.`；非法的 `baseUrl` 会抛出 `webScrapingApi baseUrl must be a valid URL.`
>
> 您传入的凭据还决定了 SDK 调用哪个 API。`apiKey` 使用位于 `data.decodo.com` 的 Web Data API，这也是使用搜索、站点地图和爬取功能的唯一途径。`token` 使用位于 `scraper-api.decodo.com` 的旧版 Web Scraping API，该 API 仅支持抓取。

## 抓取

通过 `client.webScrapingApi` 访问该 API。下面的示例假定您已导入 `Target`，并在需要时一并导入 `DecodoClient`：

```typescript theme={null}
import { DecodoClient, Target } from '@decodo/sdk-ts';
```

### 同步抓取

等待抓取结果返回后再继续：

```typescript theme={null}
const result = await client.webScrapingApi.scrape({
  target: Target.AmazonProduct,
  query: 'B09H74FXNW',
  parse: true,
});
```

### 异步抓取

创建抓取任务并立即返回。任务状态和结果需另行轮询：

```typescript theme={null}
const task = await client.webScrapingApi.scrapeAsync({
  target: Target.GoogleSearch,
  query: 'laptop reviews',
  parse: true,
});

const meta = await client.webScrapingApi.getStatus(task.id);
console.log(meta.status); // 'pending' | 'done' | 'faulted'

const results = await client.webScrapingApi.getResults(task.id);
```

### 批量抓取

在单个请求中发送多个查询或 URL：

```typescript theme={null}
const batch = await client.webScrapingApi.scrapeBatch({
  target: Target.GoogleSearch,
  query: ['coffee', 'tea', 'juice'],
  parse: true,
});

const coffeeTaskId = batch.queries[0].id;
await client.webScrapingApi.getResults(coffeeTaskId);
```

## Web Data API：搜索、站点地图和爬取

这些方法由位于 `data.decodo.com` 的 Web Data API 提供，**需要 `apiKey`**。在配置了基本身份验证 `token` 的客户端上调用它们，会在发出任何请求之前就抛出异常，例如：`search() requires webScrapingApi.apiKey. A Basic token cannot call the Data API.`

### 搜索

运行一次网页搜索并返回结果页面：

```typescript theme={null}
const serp = await client.webScrapingApi.search({
  query: 'laptop reviews',
  geo: 'United States',
});
```

### 站点地图

发现站点上的链接：

```typescript theme={null}
const map = await client.webScrapingApi.map({
  url: 'https://example.com',
  limit: 100,
});

const links = map.results[0].content.links;
```

### 爬取

`crawl()` 会启动爬取、轮询其状态，并在任务结束后返回所有页面：

```typescript theme={null}
const { status, pages } = await client.webScrapingApi.crawl(
  { url: 'https://example.com', limit: 50, output: 'markdown' },
  { pollInterval: 5_000, timeout: 600_000 },
);

console.log(status.status, status.completed, status.failed); // 'done' 12 0
```

> [!WARNING]
>
> 这里返回的 `status` 是完整的状态**对象**，而不是字符串——状态本身位于 `status.status`。像 `if (status === 'done')` 这样的判断永远不会成立。该对象还包含 `crawl_id`、`discovered`、`completed`、`failed` 和 `in_flight`。

若要逐步控制爬取流程，请先启动爬取，再分别轮询状态和页面：

```typescript theme={null}
const job = await client.webScrapingApi.startCrawl({ url: 'https://example.com' });

const progress = await client.webScrapingApi.getCrawlStatus(job.crawl_id);
console.log(progress.status); // 'pending' | 'done' | 'faulted' | 'cancelled' | 'truncated'

const pages = await client.webScrapingApi.getCrawlResults(job.crawl_id);

await client.webScrapingApi.cancelCrawl(job.crawl_id);
```

对于大规模爬取，`listCrawlPages()` 每次返回一批基于游标分页的结果。请把 `next` 的值作为 `cursor` 再次传入，直到它为空：

```typescript theme={null}
let cursor;

do {
  const page = await client.webScrapingApi.listCrawlPages(job.crawl_id, { cursor });
  for (const p of page.pages) console.log(p.url, p.status);
  cursor = page.next;
} while (cursor);
```

| 方法 | 说明 |
| - | - |
| `search(params)` | 运行网页搜索并返回结果页面 |
| `map(params)` | 列出站点上的链接，而不获取其内容 |
| `crawl(params, options)` | 启动爬取、等待其完成，并返回 `{ status, pages }` |
| `startCrawl(params)` | 启动爬取并立即返回其 `crawl_id` |
| `getCrawlStatus(crawlId)` | 报告进度和当前状态 |
| `getCrawlResults(crawlId)` | 获取所有已爬取的页面 |
| `listCrawlPages(crawlId, options)` | 获取一批游标分页结果：`{ pages, next, total }` |
| `cancelCrawl(crawlId)` | 停止正在运行的爬取 |

## 支持的目标

每个目标接受一个主输入参数（`url`、`query`、`product_id` 或 `prompt`），以及可选的配置项。

### 搜索引擎

| 目标 | 说明 | 示例 |
| - | - | - |
| `Target.GoogleSearch` | 某个查询的 Google 搜索结果 | `{ target: Target.GoogleSearch, query: "coffee shops" }` |
| `Target.GoogleMaps` | Google 地图搜索结果 | `{ target: Target.GoogleMaps, query: "coffee shops brooklyn" }` |
| `Target.GoogleShoppingSearch` | Google Shopping 搜索结果 | `{ target: Target.GoogleShoppingSearch, query: "laptop" }` |
| `Target.GoogleShoppingProduct` | Google Shopping 商品页面。**目前会返回错误**——详见下方说明 | `{ target: Target.GoogleShoppingProduct, query: "laptop" }` |
| `Target.GoogleSuggest` | Google 自动补全建议。**目前会返回错误**——详见下方说明 | `{ target: Target.GoogleSuggest, query: "coffee" }` |
| `Target.GoogleLens` | Google Lens 以图搜图 | `{ target: Target.GoogleLens, query: "https://example.com/cat.jpg" }` |
| `Target.GoogleAds` | 某个查询的 Google Ads 结果 | `{ target: Target.GoogleAds, query: "laptop" }` |
| `Target.GoogleTravelHotels` | Google Travel 酒店列表 | `{ target: Target.GoogleTravelHotels, query: "hotels in paris" }` |
| `Target.GoogleTrendsExplore` | Google Trends Explore 数据 | `{ target: Target.GoogleTrendsExplore, query: "web scraping" }` |
| `Target.BingSearch` | Bing 搜索结果 | `{ target: Target.BingSearch, query: "electric vehicles" }` |

### 电商

| 目标 | 说明 | 示例 |
| - | - | - |
| `Target.AmazonProduct` | 按 ASIN 获取 Amazon 商品详情页 | `{ target: Target.AmazonProduct, query: "B09H74FXNW" }` |
| `Target.AmazonSearch` | Amazon 搜索结果 | `{ target: Target.AmazonSearch, query: "laptop" }` |
| `Target.AmazonPricing` | Amazon 价格和报价 | `{ target: Target.AmazonPricing, query: "B09H74FXNW" }` |
| `Target.AmazonSellers` | Amazon 卖家列表 | `{ target: Target.AmazonSellers, query: "A1R0Z7FJGTKESH" }` |
| `Target.AmazonBestsellers` | 按类目获取 Amazon 畅销榜 | `{ target: Target.AmazonBestsellers, query: "electronics" }` |
| `Target.WalmartProduct` | 按商品 ID 获取 Walmart 商品页面 | `{ target: Target.WalmartProduct, product_id: "15296401808" }` |
| `Target.WalmartSearch` | Walmart 搜索结果 | `{ target: Target.WalmartSearch, query: "laptop" }` |
| `Target.TargetProduct` | 按商品 ID 获取 Target.com 商品页面 | `{ target: Target.TargetProduct, product_id: "92186007" }` |
| `Target.TargetSearch` | Target.com 搜索结果 | `{ target: Target.TargetSearch, query: "laptop" }` |
| `Target.LowesSearch` | Lowe's 搜索结果 | `{ target: Target.LowesSearch, query: "drill" }` |
| `Target.Ecommerce` | 通用电商页面，带解析器 | `{ target: Target.Ecommerce, url: "https://example.com/product/123" }` |

### 社交媒体

| 目标 | 说明 | 示例 |
| - | - | - |
| `Target.YoutubeVideo` | 按 ID 获取 YouTube 视频。**目前会返回错误**——详见下方说明 | `{ target: Target.YoutubeVideo, query: "dFu9aKJoqGg" }` |
| `Target.YoutubeSearch` | YouTube 搜索结果 | `{ target: Target.YoutubeSearch, query: "ambient music" }` |
| `Target.YoutubeSearchMax` | YouTube 搜索结果，扩展结果集 | `{ target: Target.YoutubeSearchMax, query: "ambient music" }` |
| `Target.YoutubeMetadata` | 按 ID 获取 YouTube 视频元数据 | `{ target: Target.YoutubeMetadata, query: "dFu9aKJoqGg" }` |
| `Target.YoutubeSubtitles` | 按 ID 获取 YouTube 视频字幕 | `{ target: Target.YoutubeSubtitles, query: "dFu9aKJoqGg" }` |
| `Target.YoutubeTranscript` | 按 ID 获取 YouTube 视频转录文本。必须提供 `language_code` | `{ target: Target.YoutubeTranscript, query: "dFu9aKJoqGg", language_code: "en" }` |
| `Target.YoutubeChannel` | 按 handle 或 ID 获取 YouTube 频道 | `{ target: Target.YoutubeChannel, query: "@decodo_official" }` |
| `Target.TiktokPost` | 按 URL 获取 TikTok 帖子 | `{ target: Target.TiktokPost, url: "https://www.tiktok.com/@nba/video/..." }` |
| `Target.TiktokShopSearch` | TikTok Shop 搜索结果 | `{ target: Target.TiktokShopSearch, query: "wireless earbuds" }` |
| `Target.TiktokShopProduct` | 按商品 ID 获取 TikTok Shop 商品页面 | `{ target: Target.TiktokShopProduct, product_id: "7100000000000000000" }` |
| `Target.InstagramGraphqlProfile` | 按用户名获取 Instagram 个人主页 | `{ target: Target.InstagramGraphqlProfile, query: "decodo_official" }` |

### AI 工具

| 目标 | 说明 | 示例 |
| - | - | - |
| `Target.Chatgpt` | 针对某个提示词的 ChatGPT 回答 | `{ target: Target.Chatgpt, prompt: "What are the top three dog breeds?" }` |
| `Target.Perplexity` | 针对某个提示词的 Perplexity 回答 | `{ target: Target.Perplexity, prompt: "What causes seasonal allergies?" }` |
| `Target.Gemini` | 针对某个提示词的 Gemini 回答 | `{ target: Target.Gemini, prompt: "What are the top three dog breeds?" }` |
| `Target.GoogleAiMode` | Google AI 模式的回答 | `{ target: Target.GoogleAiMode, query: "What are the top three dog breeds?" }` |

### 其他

| 目标 | 说明 | 示例 |
| - | - | - |
| `Target.Bbb` | 按 URL 获取 Better Business Bureau 条目 | `{ target: Target.Bbb, url: "https://bbb.org/us/ny/new-york/..." }` |
| `Target.Autotrader` | 按 URL 获取 Autotrader 条目 | `{ target: Target.Autotrader, url: "https://autotrader.com/cars-for-sale/..." }` |
| `Target.Mobile` | 按 URL 获取 Mobile.de 条目 | `{ target: Target.Mobile, url: "https://mobile.de/auto/..." }` |
| `Target.AppleAppStore` | 按 URL 获取 Apple App Store 应用 | `{ target: Target.AppleAppStore, url: "https://apps.apple.com/app/id12345" }` |
| `Target.Airbnb` | 按 URL 获取 Airbnb 房源 | `{ target: Target.Airbnb, url: "https://airbnb.com/rooms/12345" }` |

### 通用目标与原始 URL 抓取

| 目标 | 说明 | 示例 |
| - | - | - |
| `Target.Universal` | 通过通用抓取器抓取任意 URL | `{ target: Target.Universal, url: "https://example.com" }` |
| `Target.Google` | 原始 Google URL 抓取 | `{ target: Target.Google, url: "https://google.com/search?q=laptop" }` |
| `Target.Bing` | 原始 Bing URL 抓取 | `{ target: Target.Bing, url: "https://bing.com/search?q=laptop" }` |
| `Target.Amazon` | 原始 Amazon URL 抓取 | `{ target: Target.Amazon, url: "https://amazon.com/dp/B09H74FXNW" }` |
| `Target.Walmart` | 原始 Walmart URL 抓取 | `{ target: Target.Walmart, url: "https://walmart.com/ip/15296401808" }` |
| `Target.Target` | 原始 Target.com URL 抓取 | `{ target: Target.Target, url: "https://target.com/p/-/A-92186007" }` |
| `Target.Tiktok` | 原始 TikTok URL 抓取 | `{ target: Target.Tiktok, url: "https://www.tiktok.com/@nba" }` |

> [!WARNING]
>
> **有十二个目标早于当前的 API schema。** Decodo 各 SDK 均由同一份 schema 生成；TypeScript SDK 目前提供的是 v2.1.1 的目标集合，而 [**Python**](https://help.decodo.com/docs/cn/python-sdk.md) 和 [**Go**](https://help.decodo.com/docs/cn/go-sdk.md) SDK 已是 v2.3.0。下列十二个目标仅存在于 TypeScript SDK 中：
>
> `ecommerce`、`google_maps`、`google_shopping_product`、`google_shopping_search`、`google_suggest`、`google_trends_explore`、`instagram_graphql_profile`、`lowes_search`、`universal_ecommerce`、`youtube_search_max`、`youtube_transcript`、`youtube_video`
>
> 其中大多数仍可正常使用。有三个无法使用，目前会返回错误：**`google_suggest`**、**`youtube_video`** 和 **`google_shopping_product`**。请在新代码中避免使用这三个目标。如果您需要 Google Shopping 数据，`google_shopping_search` 可以正常工作。

> [!NOTE]
>
> `Target.UniversalEcommerce` 未列入上述表格，因为它不接受 `url`、`query`、`product_id` 或 `prompt` 这类主输入参数。它只接受 `callback_url` 等可选配置字段。

完整的目标列表和参数详情，请参阅[**目标列表**](https://help.decodo.com/docs/cn/web-scraping-api-targets.md)和[**参数**](https://help.decodo.com/docs/web-scraping-api-parameters-overview.md)。

## 错误处理

该 SDK 会抛出与 API 错误码对应的类型化错误：

```typescript theme={null}
import {
  DecodoError,
  AuthenticationError,
  RateLimitError,
  ValidationError,
  TimeoutError,
  Target,
} from '@decodo/sdk-ts';

try {
  await client.webScrapingApi.scrape({
    target: Target.GoogleSearch,
    query: 'test',
    parse: true,
  });
} catch (err) {
  if (err instanceof AuthenticationError) {
    // 401/403 - bad credentials
  } else if (err instanceof RateLimitError) {
    // 429 - too many requests
  } else if (err instanceof ValidationError) {
    // 422 - invalid parameters
    console.log(err.errors);
  } else if (err instanceof TimeoutError) {
    // request timed out
  }
}
```

`AuthenticationError`、`RateLimitError` 和 `ValidationError` 都继承自 `DecodoError`。`TimeoutError` 不在 `DecodoError` 的层级之内，因此请单独处理。

***

## 相关内容

* [**CLI**](https://help.decodo.com/docs/cn/cli.md)：在命令行中运行 Decodo 抓取工作流。
* [**Python SDK**](https://help.decodo.com/docs/cn/python-sdk.md)：将 Decodo API 集成到 Python 项目中。
* [**Go SDK**](https://help.decodo.com/docs/cn/go-sdk.md)：将 Decodo API 集成到 Go 项目中。
* [**MCP 服务器**](https://help.decodo.com/docs/cn/mcp.md)：将 AI 智能体和兼容 MCP 的工具连接到 Decodo。
* [GitHub 仓库](https://github.com/Decodo/sdk-ts)：查看 TypeScript SDK 的源代码、示例和最新版本。

***

> [card] [支持](https://direct.lc.chat/12092754)
>
> 需要帮助或只是想打个招呼？我们的支持团队全天候为您服务。 \
> 您也可以随时通过电子邮件 [support@decodo.com](mailto:support@decodo.com) 联系我们。

> [card] [反馈](mailto:feedback@decodo.com)
>
> 找不到您要找的内容？请求一篇文章！ \
> 有反馈意见？分享您对我们如何改进的想法。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.