@fetcher-sh/api

中文文档
1.0.1发布于 2026/08/14MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 7945

The developer-friendly client for fetcher.sh — 111 pay-per-call web-data endpoints across Twitter/X, YouTube, TikTok, Instagram, Reddit, Google, App Store, and Yelp. Use as an NPM library or CLI.

原始使用文档
文档目录20 节
  1. Prerequisites
  2. Installation
  3. Quick start (library)
  4. Services & methods
  5. The generic escape hatch
  6. Pagination
  7. Paying per call with x402 (no key)
  8. Credits
  9. Error handling
  10. CLI
  11. Setup
  12. Commands
  13. Output options
  14. Global flags
  15. API reference
  16. new Fetcher(options?)
  17. Request options (per call)
  18. Statics
  19. Notes
  20. License

@fetcher-sh/api

The developer-friendly client for fetcher.sh — 111 pay-per-call web-data endpoints across Twitter/X, YouTube, TikTok, Instagram, Reddit, Google Search, Google Maps, Google News, Google Play, the App Store, and Yelp. Use it as an NPM library or a CLI.

Every endpoint is a plain GET returning a stable { status, message, data } envelope. Pay per call in USDC via x402, or top up once and spend a single prepaid balance across all 11 services — the same bby_live_ key works everywhere.

Prerequisites

  • Node.js 18+ (uses the built-in fetch).
  • One of:
    • A prepaid API key (bby_live_...) — get one at fetcher.sh/topup, or
    • A wallet holding a few cents of USDC on Base, Polygon, Arbitrum, Monad, or Solana, for pay-per-call x402 (no key needed).

Installation

npm install @fetcher-sh/api

Quick start (library)

// ESM
import { Fetcher } from "@fetcher-sh/api";

// CommonJS
const { Fetcher } = require("@fetcher-sh/api");

const fetcher = new Fetcher({ apiKey: process.env.FETCHER_API_KEY });

// Search tweets
const tweets = await fetcher.twitter.search({ query: "x402" });

// Look up an Instagram profile by handle
const profile = await fetcher.instagram.userByHandle("nasa");

// Clean Google web-search results
const serp = await fetcher.google.search({ query: "climate change" });

console.log(tweets, profile, serp);

By default every method returns just the data field. Pass { fullResponse: true } to get the whole { status, message, data } envelope.

const env = await fetcher.reddit.searchPosts(
  { query: "bitcoin" },
  { fullResponse: true },
);
console.log(env.status, env.message, env.data);

If the apiKey is omitted it falls back to the FETCHER_API_KEY environment variable.

Services & methods

One balance, eleven services. Each namespace maps 1:1 to the endpoints in the live catalog.

NamespaceAccess viaHighlights
Twitter / Xfetcher.twitter / fetcher.xsearch, handle, user, userTweets, userFollowers, tweet, tweetReplies, trends, listTweets
YouTubefetcher.youtubesearchVideo, video, videoComments, channel, channelVideos, trending, playlistVideos
TikTokfetcher.tiktoksearchPosts, postByUrl, userByHandle, userPosts, hashtagPosts, musicPosts
Instagramfetcher.instagramuserByHandle, user, userPosts, userReels, userStories, hashtagPosts, postByCode
Redditfetcher.redditsearchPosts, subredditPosts, post, postComments, postsHot, user, userComments
Google Searchfetcher.googlesearch
Google Mapsfetcher.googleMapssearchPlaces, place, placeReviews, review
Google Newsfetcher.googleNewssearch, latest, world, business, technology, topic, decodeArticleUrl
Google Playfetcher.googlePlaysearchApps, app, appReviews, appPermissions, appDataSafety, developer
App Storefetcher.appStoresearchApps, app, appReviews, appSimilar, bundle, developer
Yelpfetcher.yelpsearch, place, placeByHandle, placeReviews

The generic escape hatch

Any endpoint — even ones without a named helper — is reachable with get:

await fetcher.get("/api/twitter/search", { params: { query: "x402" } });
await fetcher.get("/api/reddit/subreddit/programming/posts");

Pagination

Paginated endpoints return an opaque cursor. Pass it back to fetch the next page:

let cursor: string | undefined;
do {
  const page = await fetcher.twitter.userFollowers("44196397", {
    fullResponse: true,
    params: { cursor },
  });
  // ...process page.data...
  cursor = (page.data as any)?.cursor;
} while (cursor);

Paying per call with x402 (no key)

Skip the API key and pass a payment-wrapped fetch instead. The client stays dependency-free — you bring the wallet:

import { Fetcher } from "@fetcher-sh/api";
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: ["eip155:8453", "eip155:137", "eip155:42161", "eip155:143"].map(
    (network) => ({ network, client: new ExactEvmScheme(account) }),
  ),
});

const fetcher = new Fetcher({ fetch: fetchWithPayment });
const tweets = await fetcher.twitter.search({ query: "x402" }); // 402 → sign → retry, automatically

Gas is sponsored, so the wallet needs no native token — just USDC on any supported chain.

Credits

// Read the shared balance (needs an API key)
const balance = await fetcher.credits.balance();
console.log(balance.balance_usd);

// Top up (x402-paid; requires a payment-wrapped fetch). The first top-up
// returns the bby_live_ key EXACTLY ONCE — store it, it cannot be recovered.
const result = await fetcher.credits.topup(5);
console.log(result.key);

Error handling

Every non-2xx response throws a FetcherError carrying the status, parsed envelope, and helpers:

import { FetcherError } from "@fetcher-sh/api";

try {
  await fetcher.twitter.search({ query: "x402" });
} catch (err) {
  if (err instanceof FetcherError) {
    if (err.isTopupRequired) console.error("Out of credits — top up.");
    else if (err.isUnauthorized) console.error("Bad or rotated API key.");
    else if (err.isPaymentRequired) console.error("x402 payment required.");
    else console.error(err.status, err.message);
  }
}

CLI

Install globally to use from the command line:

npm install -g @fetcher-sh/api

Setup

# Store your API key (saved to ~/.fetcher-sh/config.json)
fetcher init --token bby_live_xxx

# Or set it as an environment variable
export FETCHER_API_KEY=bby_live_xxx

# Or pass it per command
fetcher balance --token bby_live_xxx

Commands

# Shortcuts for each service's hero endpoint
fetcher twitter-search "x402"
fetcher youtube-search "lofi hip hop"
fetcher tiktok-search "cats"
fetcher instagram-user nasa
fetcher reddit-search "bitcoin"
fetcher google-search "climate change"
fetcher google-maps-search "coffee near me"
fetcher google-news-search "artificial intelligence"
fetcher googleplay-apps "notes"
fetcher appstore-apps "notes"
fetcher yelp-search "coffee" --location "San Francisco"

# Call ANY endpoint by path; extra --flags become query params
fetcher get /api/twitter/user/44196397/tweets --cursor abc123
fetcher get /api/reddit/subreddit/programming/posts

# Credits
fetcher balance
fetcher topup --amount 5          # needs an x402 wallet — see notes

# Explore the catalog
fetcher services
fetcher endpoints twitter

Output options

fetcher twitter-search "x402"              # pretty JSON (default)
fetcher twitter-search "x402" --json       # compact JSON
fetcher twitter-search "x402" --jsonl      # one object per line (arrays)
fetcher twitter-search "x402" --output out.json
fetcher get /api/x/y --debug               # show raw error bodies

Global flags

FlagDescription
--token <key>API key (bby_live_...); overrides env & config
--base-url <url>Override the API base URL
--jsonCompact JSON output
--jsonlOne JSON object per line (arrays only)
--output <file>Write output to a file
--<key> <value>Any extra query parameter (e.g. --cursor, --location)

API reference

new Fetcher(options?)

OptionTypeDefaultDescription
apiKeystringFETCHER_API_KEY envPrepaid-credits key (bby_live_...)
baseUrlstringhttps://fetcher.shAPI base URL
fetchFetchLikeglobal fetchCustom fetch (e.g. x402 payment-wrapped)
timeoutnumber30000Default request timeout in ms
headersobject{}Extra headers on every request

Request options (per call)

OptionTypeDescription
fullResponsebooleanReturn { status, message, data } instead of just data
paramsobjectExtra query parameters
timeoutnumberPer-request timeout in ms
signalAbortSignalCancel the request

Statics

  • Fetcher.endpoints() — the full catalog of 111 priced endpoints.
  • Fetcher.services() — per-service metadata (host, count, summary).
  • Fetcher.priceOf(path) — USD price for a path (templated paths supported).

Notes

  • Read-only by design. Every endpoint is a GET — no writes, follows, or posts.
  • No rate limits. Your balance (or wallet) is the natural backpressure.
  • No refunds on upstream failure. Settlement precedes delivery.
  • This is an unofficial client for fetcher.sh, which itself is an independent proxy with no affiliation to X, TikTok, Meta, Google, Yelp, or Apple.

License

MIT

版本与发布记录

@fetcher-sh/api 共发布 1 个版本,首次发布于 2026/08/14;过去 12 个月发布了 1 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.0.1latest2026/08/143 个月前

关于 @fetcher-sh/api 的常见问题

@fetcher-sh/api 是什么?

The developer-friendly client for fetcher.sh — 111 pay-per-call web-data endpoints across Twitter/X, YouTube, TikTok, Instagram, Reddit, Google, App Store, and Yelp. Use as an NPM library or CLI.

如何安装 @fetcher-sh/api?

在项目目录运行 npm install @fetcher-sh/api,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 fetcher,可以用 npx fetcher 直接运行。

@fetcher-sh/api 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@fetcher-sh/api 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@fetcher-sh/api 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@fetcher-sh/api 可以商用吗?

@fetcher-sh/api 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@fetcher-sh/api 的下载量有多少?

根据 npm 官方下载统计,@fetcher-sh/api 在 2026/10/15 – 2026/11/13 这 30 天内被下载 7,945 次,日均约 265 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@fetcher-sh/api 还在维护吗?

最新版本 1.0.1 发布于 2026/08/14(3 个月前);至今共发布 1 个版本,其中过去 12 个月发布了 1 个;首次发布于 2026/08/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。