{"_id":"@fetcher-sh/api","name":"@fetcher-sh/api","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.1":{"name":"@fetcher-sh/api","version":"1.0.1","description":"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.","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"bin":{"fetcher":"dist/cli.js"},"publishConfig":{"access":"public"},"scripts":{"build":"node build.js && tsc --emitDeclarationOnly --declaration --outDir dist","prepublishOnly":"npm run build","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit"},"keywords":["fetcher","fetcher.sh","x402","web-data","scraper","twitter","x","youtube","tiktok","instagram","reddit","google","google-maps","google-news","google-play","app-store","yelp","usdc","api","agents","mcp"],"author":{"name":"fetcher.sh"},"license":"MIT","homepage":"https://fetcher.sh","repository":{"type":"git","url":"git+https://github.com/fetcher-sh/npm-fetcher-sh.git"},"bugs":{"url":"https://github.com/fetcher-sh/npm-fetcher-sh/issues"},"engines":{"node":">=18"},"devDependencies":{"@types/node":"^22.0.0","esbuild":"^0.24.0","typescript":"^5.6.0","vitest":"^2.1.0"},"_id":"@fetcher-sh/api@1.0.1","gitHead":"440058579a775e3c6e9ecdaa621f9d7dc62bcec0","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-yGlGJrO+iLfQpN2ZGYrsjY4StxzElQP4nkkMO0vBwmf2+BlaCUuwdM/vSrsYehjCkcuiRoxgcP1KFB33C+ohIg==","shasum":"1227c8dc1a4f5eb90f350b6f39c3fb520756bd04","tarball":"https://registry.npmjs.org/@fetcher-sh/api/-/api-1.0.1.tgz","fileCount":49,"unpackedSize":496706,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@fetcher-sh%2fapi@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD+KWorxYuXpZvC1smcZbRmADX7TNIWH8yahtfDkMZ5aAIgaX4u2C4nAvPUCAE8eC6bVyGReoaiOlRlnzK2NL0RjjU="}]},"_npmUser":{"name":"fetcher-sh","email":"info@fetcher.sh"},"directories":{},"maintainers":[{"name":"fetcher-sh","email":"info@fetcher.sh"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/api_1.0.1_1786714601124_0.976054161739238"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-14T13:36:40.970Z","1.0.1":"2026-08-14T13:36:41.343Z","modified":"2026-08-14T13:36:41.774Z"},"maintainers":[{"name":"fetcher-sh","email":"info@fetcher.sh"}],"description":"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.","homepage":"https://fetcher.sh","keywords":["fetcher","fetcher.sh","x402","web-data","scraper","twitter","x","youtube","tiktok","instagram","reddit","google","google-maps","google-news","google-play","app-store","yelp","usdc","api","agents","mcp"],"repository":{"type":"git","url":"git+https://github.com/fetcher-sh/npm-fetcher-sh.git"},"author":{"name":"fetcher.sh"},"bugs":{"url":"https://github.com/fetcher-sh/npm-fetcher-sh/issues"},"license":"MIT","readme":"# @fetcher-sh/api\n\nThe developer-friendly client for [**fetcher.sh**](https://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**.\n\nEvery endpoint is a plain `GET` returning a stable `{ status, message, data }` envelope. Pay per call in USDC via [x402](https://fetcher.sh), or top up once and spend a single prepaid balance across all 11 services — the same `bby_live_` key works everywhere.\n\n## Prerequisites\n\n- **Node.js 18+** (uses the built-in `fetch`).\n- **One of:**\n  - A prepaid **API key** (`bby_live_...`) — get one at [fetcher.sh/topup](https://fetcher.sh/topup), or\n  - A **wallet** holding a few cents of USDC on Base, Polygon, Arbitrum, Monad, or Solana, for pay-per-call x402 (no key needed).\n\n## Installation\n\n```bash\nnpm install @fetcher-sh/api\n```\n\n## Quick start (library)\n\n```ts\n// ESM\nimport { Fetcher } from \"@fetcher-sh/api\";\n\n// CommonJS\nconst { Fetcher } = require(\"@fetcher-sh/api\");\n\nconst fetcher = new Fetcher({ apiKey: process.env.FETCHER_API_KEY });\n\n// Search tweets\nconst tweets = await fetcher.twitter.search({ query: \"x402\" });\n\n// Look up an Instagram profile by handle\nconst profile = await fetcher.instagram.userByHandle(\"nasa\");\n\n// Clean Google web-search results\nconst serp = await fetcher.google.search({ query: \"climate change\" });\n\nconsole.log(tweets, profile, serp);\n```\n\nBy default every method returns just the `data` field. Pass `{ fullResponse: true }` to get the whole `{ status, message, data }` envelope.\n\n```ts\nconst env = await fetcher.reddit.searchPosts(\n  { query: \"bitcoin\" },\n  { fullResponse: true },\n);\nconsole.log(env.status, env.message, env.data);\n```\n\nIf the `apiKey` is omitted it falls back to the `FETCHER_API_KEY` environment variable.\n\n## Services & methods\n\nOne balance, eleven services. Each namespace maps 1:1 to the endpoints in the [live catalog](https://fetcher.sh/llms.txt).\n\n| Namespace | Access via | Highlights |\n| --- | --- | --- |\n| Twitter / X | `fetcher.twitter` / `fetcher.x` | `search`, `handle`, `user`, `userTweets`, `userFollowers`, `tweet`, `tweetReplies`, `trends`, `listTweets` |\n| YouTube | `fetcher.youtube` | `searchVideo`, `video`, `videoComments`, `channel`, `channelVideos`, `trending`, `playlistVideos` |\n| TikTok | `fetcher.tiktok` | `searchPosts`, `postByUrl`, `userByHandle`, `userPosts`, `hashtagPosts`, `musicPosts` |\n| Instagram | `fetcher.instagram` | `userByHandle`, `user`, `userPosts`, `userReels`, `userStories`, `hashtagPosts`, `postByCode` |\n| Reddit | `fetcher.reddit` | `searchPosts`, `subredditPosts`, `post`, `postComments`, `postsHot`, `user`, `userComments` |\n| Google Search | `fetcher.google` | `search` |\n| Google Maps | `fetcher.googleMaps` | `searchPlaces`, `place`, `placeReviews`, `review` |\n| Google News | `fetcher.googleNews` | `search`, `latest`, `world`, `business`, `technology`, `topic`, `decodeArticleUrl` |\n| Google Play | `fetcher.googlePlay` | `searchApps`, `app`, `appReviews`, `appPermissions`, `appDataSafety`, `developer` |\n| App Store | `fetcher.appStore` | `searchApps`, `app`, `appReviews`, `appSimilar`, `bundle`, `developer` |\n| Yelp | `fetcher.yelp` | `search`, `place`, `placeByHandle`, `placeReviews` |\n\n### The generic escape hatch\n\nAny endpoint — even ones without a named helper — is reachable with `get`:\n\n```ts\nawait fetcher.get(\"/api/twitter/search\", { params: { query: \"x402\" } });\nawait fetcher.get(\"/api/reddit/subreddit/programming/posts\");\n```\n\n### Pagination\n\nPaginated endpoints return an opaque `cursor`. Pass it back to fetch the next page:\n\n```ts\nlet cursor: string | undefined;\ndo {\n  const page = await fetcher.twitter.userFollowers(\"44196397\", {\n    fullResponse: true,\n    params: { cursor },\n  });\n  // ...process page.data...\n  cursor = (page.data as any)?.cursor;\n} while (cursor);\n```\n\n## Paying per call with x402 (no key)\n\nSkip the API key and pass a payment-wrapped `fetch` instead. The client stays dependency-free — you bring the wallet:\n\n```ts\nimport { Fetcher } from \"@fetcher-sh/api\";\nimport { wrapFetchWithPaymentFromConfig } from \"@x402/fetch\";\nimport { ExactEvmScheme } from \"@x402/evm/exact/client\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nconst account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);\nconst fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {\n  schemes: [\"eip155:8453\", \"eip155:137\", \"eip155:42161\", \"eip155:143\"].map(\n    (network) => ({ network, client: new ExactEvmScheme(account) }),\n  ),\n});\n\nconst fetcher = new Fetcher({ fetch: fetchWithPayment });\nconst tweets = await fetcher.twitter.search({ query: \"x402\" }); // 402 → sign → retry, automatically\n```\n\nGas is sponsored, so the wallet needs no native token — just USDC on any supported chain.\n\n## Credits\n\n```ts\n// Read the shared balance (needs an API key)\nconst balance = await fetcher.credits.balance();\nconsole.log(balance.balance_usd);\n\n// Top up (x402-paid; requires a payment-wrapped fetch). The first top-up\n// returns the bby_live_ key EXACTLY ONCE — store it, it cannot be recovered.\nconst result = await fetcher.credits.topup(5);\nconsole.log(result.key);\n```\n\n## Error handling\n\nEvery non-2xx response throws a `FetcherError` carrying the status, parsed envelope, and helpers:\n\n```ts\nimport { FetcherError } from \"@fetcher-sh/api\";\n\ntry {\n  await fetcher.twitter.search({ query: \"x402\" });\n} catch (err) {\n  if (err instanceof FetcherError) {\n    if (err.isTopupRequired) console.error(\"Out of credits — top up.\");\n    else if (err.isUnauthorized) console.error(\"Bad or rotated API key.\");\n    else if (err.isPaymentRequired) console.error(\"x402 payment required.\");\n    else console.error(err.status, err.message);\n  }\n}\n```\n\n## CLI\n\nInstall globally to use from the command line:\n\n```bash\nnpm install -g @fetcher-sh/api\n```\n\n### Setup\n\n```bash\n# Store your API key (saved to ~/.fetcher-sh/config.json)\nfetcher init --token bby_live_xxx\n\n# Or set it as an environment variable\nexport FETCHER_API_KEY=bby_live_xxx\n\n# Or pass it per command\nfetcher balance --token bby_live_xxx\n```\n\n### Commands\n\n```bash\n# Shortcuts for each service's hero endpoint\nfetcher twitter-search \"x402\"\nfetcher youtube-search \"lofi hip hop\"\nfetcher tiktok-search \"cats\"\nfetcher instagram-user nasa\nfetcher reddit-search \"bitcoin\"\nfetcher google-search \"climate change\"\nfetcher google-maps-search \"coffee near me\"\nfetcher google-news-search \"artificial intelligence\"\nfetcher googleplay-apps \"notes\"\nfetcher appstore-apps \"notes\"\nfetcher yelp-search \"coffee\" --location \"San Francisco\"\n\n# Call ANY endpoint by path; extra --flags become query params\nfetcher get /api/twitter/user/44196397/tweets --cursor abc123\nfetcher get /api/reddit/subreddit/programming/posts\n\n# Credits\nfetcher balance\nfetcher topup --amount 5          # needs an x402 wallet — see notes\n\n# Explore the catalog\nfetcher services\nfetcher endpoints twitter\n```\n\n### Output options\n\n```bash\nfetcher twitter-search \"x402\"              # pretty JSON (default)\nfetcher twitter-search \"x402\" --json       # compact JSON\nfetcher twitter-search \"x402\" --jsonl      # one object per line (arrays)\nfetcher twitter-search \"x402\" --output out.json\nfetcher get /api/x/y --debug               # show raw error bodies\n```\n\n### Global flags\n\n| Flag | Description |\n| --- | --- |\n| `--token <key>` | API key (`bby_live_...`); overrides env & config |\n| `--base-url <url>` | Override the API base URL |\n| `--json` | Compact JSON output |\n| `--jsonl` | One JSON object per line (arrays only) |\n| `--output <file>` | Write output to a file |\n| `--<key> <value>` | Any extra query parameter (e.g. `--cursor`, `--location`) |\n\n## API reference\n\n### `new Fetcher(options?)`\n\n| Option | Type | Default | Description |\n| --- | --- | --- | --- |\n| `apiKey` | `string` | `FETCHER_API_KEY` env | Prepaid-credits key (`bby_live_...`) |\n| `baseUrl` | `string` | `https://fetcher.sh` | API base URL |\n| `fetch` | `FetchLike` | global `fetch` | Custom fetch (e.g. x402 payment-wrapped) |\n| `timeout` | `number` | `30000` | Default request timeout in ms |\n| `headers` | `object` | `{}` | Extra headers on every request |\n\n### Request options (per call)\n\n| Option | Type | Description |\n| --- | --- | --- |\n| `fullResponse` | `boolean` | Return `{ status, message, data }` instead of just `data` |\n| `params` | `object` | Extra query parameters |\n| `timeout` | `number` | Per-request timeout in ms |\n| `signal` | `AbortSignal` | Cancel the request |\n\n### Statics\n\n- `Fetcher.endpoints()` — the full catalog of 111 priced endpoints.\n- `Fetcher.services()` — per-service metadata (host, count, summary).\n- `Fetcher.priceOf(path)` — USD price for a path (templated paths supported).\n\n## Notes\n\n- **Read-only by design.** Every endpoint is a `GET` — no writes, follows, or posts.\n- **No rate limits.** Your balance (or wallet) is the natural backpressure.\n- **No refunds on upstream failure.** Settlement precedes delivery.\n- 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.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-76a7e4101adef1f7f3a554e8e8f58434"}