fetch exists like Node 18+, browsers, and edge runtimes like Cloudflare Workers.
Installation
To install the Spidra Node SDK, you can use npm:Get your API key from app.spidra.io under Settings > API Keys. Never hardcode it in source files. Use an environment variable
instead.
Setup
Here’s an example of initializing the Spidra client in a Node.js or TypeScript project.Scraping
All scrape jobs run asynchronously.run() submits a job and polls until it finishes. For manual control, use submit() and get() directly. Up to 3 URLs can be passed per request and are processed in parallel.
Scrape a web page
Submit a scrape job and wait for results.Fire-and-forget approach
Fire-and-forget approach: submit a job immediately and poll on your own schedule.queued · waiting · active · completed · failed
Structured JSON output
Pass aschema to enforce an exact output shape. Missing fields come back as null rather than hallucinated values — which matters when the output feeds a database or a typed pipeline downstream.
Structured output with Zod
If you already use Zod, skip the JSON Schema entirely — pass your Zod schema and the SDK converts it for you. The result is typed from your schema, socontent needs no casting:
batch.run() (types each item’s result) and crawl.run() (types each page’s data). Zod is an optional peer dependency — install it only if you use this. Passing MySchema.shape by mistake throws a helpful error instead of failing silently.
Geo-targeted scraping
Route through a residential proxy in a specific country for geo-restricted content or localized pricing.us, gb, de, fr, jp, au, ca, br, in, nl, sg, es, it, mx, and 40+ more. Use "global" or "eu" for regional routing.
Authenticated pages
Pass session cookies as a raw header string to scrape pages behind a login.Browser actions
Run actions against the page before extraction. They execute in order — the scrape happens after all actions complete.
Use
selector for a CSS selector or XPath. Use value for plain English — Spidra locates the element using AI.
forEach — loop over every element
forEach finds a set of matching elements on the page and processes each one individually. Use it when you need to collect data from a list of items, paginate across pages, or click into each item’s detail page.
Use forEach when:
- The list spans multiple pages and you need
pagination - You need to click into each item’s detail page (
navigatemode) - You have 20+ items and want consistent per-item AI extraction (
itemPrompt)
inline mode
Read each element’s content directly without navigating away. Best for product cards, search results, and table rows.navigate mode
Follow each element’s link to its destination page and capture content there. Best for product listings where full details are only on individual pages.click mode
Click each element, capture the content that appears (modal, drawer, or expanded section), then move on. Best for hotel room cards, FAQ accordions, or any UI where clicking reveals hidden content.Pagination
After processing all elements on the current page, follow the next-page link and continue.maxItems applies across all pages combined. The loop stops when you hit maxItems, run out of elements, or reach maxPages.
Per-element actions
Run extra browser actions on each item after navigating or clicking into it, before content is captured. Useful for scrolling below the fold or expanding collapsed sections.itemPrompt vs top-level prompt
Both are optional and serve different purposes:
Use
itemPrompt to extract fields from each item individually. Use the top-level prompt to filter, sort, or reshape the combined output. They can be used together.
Controlling how long run() waits
By defaultrun() waits until the job finishes, however long that takes — so a big crawl just works. If you’d rather cap the wait, pass a timeout; when it fires, a SpidraTimeoutError is thrown and the job keeps running server-side, so you can check it later with get() or cancel it.
batch.run() and crawl.run().
Batch scraping
When you have a list of URLs to process — a product catalog, a set of listings, a pile of article links — batch is the right tool. Submit up to 50 URLs in one request and they all run in parallel. Each URL is a plain string (not an object).Scrape a list of URLs
pending · running · completed · failed
Batch statuses: pending · running · completed · failed · cancelled
Submit now, check later
If you don’t want to hold a connection open while 50 pages scrape, submit the batch and come back whenever:Stream results as they finish
Rather than waiting for the whole batch,watch() hands you each item the moment it completes — useful for writing results to a database as they arrive or updating a progress bar:
watcher.stop() stops listening without cancelling the batch.
Retry failed items
Re-queue only the items that failed — successful items are not re-run.Cancel a batch
Stops all pending items and refunds credits for unprocessed work.List past batches
Crawling
Crawling is different from scraping: you give it a starting URL and it discovers pages on its own, following links according to your instructions. Good for indexing a docs site, monitoring a competitor’s blog, or building a structured dataset from an entire section of a site.Crawl a site
Raw content mode
Omit bothtransformInstruction and schema to get the raw markdown of each page with no AI processing. No token credits are charged:
Structured output with schema
Useschema when you need every page to return the same fields in the same format:
Scoped crawling with path filters
UseincludePaths and excludePaths to keep crawls focused. Both accept glob-style patterns:
Submit now, check later
Watch a crawl page-by-page
A 50-page crawl can take a while. Instead of waiting for the whole thing,watch() streams each page to you the moment it’s crawled:
watcher.stop() stops listening without cancelling the crawl.
Cancel a crawl
Cancel a queued or running job at any time. Pages already processed are preserved:Download the raw HTML and Markdown
crawl.pages() returns signed URLs for the raw HTML and Markdown of each crawled page. Links expire after 1 hour.
Re-extract with a different prompt
Crawled a site and want to pull out different information? You don’t have to re-crawl.crawl.extract() runs a new AI pass over the already-crawled content and charges only transformation credits.
History and stats
Logs
Every API scrape job is logged automatically. Access your full history with optional filters.List and filter your logs
Get one log with its full output
Fetch a single log entry, including the complete AI extraction result for that job.Usage statistics
Returns credit and request usage broken down by day or week.Retries and reliability
You don’t have to write retry loops. Transient failures — network blips, 502/503/504 gateway errors — are retried automatically with exponential backoff, so a single hiccup never fails your call. Both knobs are configurable:Retry-After hint, the SDK honors it instead of its own backoff.
Error handling
Every non-2xx response throws a typed error class. Catch the specific class you care about, or fall back to the baseSpidraError.
All error classes expose
err.status (the HTTP status code, or 0 for non-HTTP errors like job failures and timeouts) and err.message. API errors also carry err.code (a machine-readable identifier like SERVICE_BUSY) and err.details (the raw error body).
Verifying webhooks
Crawl jobs can pushcrawl.page, crawl.completed, and crawl.failed events to your webhookUrl. Spidra signs each delivery with HMAC-SHA256 in the X-Spidra-Signature header, and the SDK ships a helper so you never accept a forged event:
AI agent integration
Spidra works as a tool inside AI agent pipelines. Here is an example using the Vercel AI SDK with Claude:SDKs Overview
Browse all official Spidra SDKs in one place.
PHP
Official PHP SDK — idiomatic helpers, typed exceptions, and configurable polling.

