Already have the URLs? Use this batch scraping guide. To discover pages from a website, follow Crawl Async (25K pages). For a small linked section returned in one response, use Crawl Sync.
Prerequisites
Create an API key at context.dev/signup, copy it from the dashboard, and export it:batches:write to submit or manage jobs; batches:read can read status and results. See API key permissions.
Choose an input
For every mode, set
input.data.format to markdown or html. Markdown output supports link and image controls in addition to the common scraping options.
Submit a fixed URL list
Each entry requires aurl. Add itemId or meta to match results to your records. Choose a new Idempotency-Key for each new job and reuse it when retrying that job.
202. Invalid URLs and duplicate pairs of normalized URL and itemId are excluded. The same URL with two different item IDs counts as two items.
sample response
Retries with the same
Idempotency-Key and request body return the original batch. Reusing the key with a different body returns 409 IDEMPOTENCY_KEY_CONFLICT. Keys can contain up to 200 characters.Scraping options
Scraping options
Common options under
input.data.options include:Markdown batches also support
includeLinks, includeImages, and shortenBase64Images. See Submit a batch for the complete schema.Crawl from a starting URL
Crawl from a starting URL
Use a
start_url source to follow links from one page. The starting URL is always included, even when regex does not match it. If the URL has no scheme, Context.dev reads it as HTTPS.controls is optional. maxUrls defaults to 100, followSubdomains defaults to false, and an omitted maxDepth allows any depth until another control stops discovery.Scrape URLs from a sitemap
Scrape URLs from a sitemap
Use a
sitemap source to scrape URLs listed by a domain. The API accepts a bare domain or a full URL and reduces it to the domain.Poll for completion
Save theid returned by submission, then replace batch_9f2c8a with that ID in the examples:
queued, running, or cancelling. Stop when it becomes completed, cancelled, or failed.
A webhook can reduce routine polling, but polling remains the fallback when delivery fails.
A crawl can complete below
maxUrls when no more eligible pages are reachable. The retrieve response repeats invalid_urls, but not webhook_secret. Store webhook_secret from the submit response immediately; it is returned only once.
Receive a webhook
Use thewebhook object in a batch submission to choose a destination and retry policy:
retry: {} for the default schedule or retry: { "delays_seconds": [] } to disable automatic retries. Custom schedules accept up to 10 delays, each 1–86,400 seconds, totaling at most 72 hours. Omitting retry preserves one legacy best-effort attempt. The older webhookUrl field also remains a single-attempt option; do not combine it with webhook.
Save webhook_secret from the submission response for a custom receiver; it is not included in later retrieve responses. Verify X-Context-Signature before using the payload. It has the form t=<unix>,v1=<hex hmac> and signs {timestamp}.{rawRequestBody} with HMAC-SHA256. Use a constant-time comparison and reject stale timestamps. The monitor verification example uses the same algorithm.
After verification, deduplicate the event ID, enqueue work, and return a 2xx promptly. Inspect delivery history and attempts, then replay a retained event after repairing your receiver. Poll batches that remain unresolved in your system; Retrieve Batch is the authoritative status and provides fresh signed result URLs.
Send batch notifications to Slack
Create a Slack or GovSlack incoming webhook for the destination channel and use its URL aswebhook.url. Terminal batch events arrive as formatted messages with a source link. Automatic retries and manual replay use the same Slack formatting. Keep the incoming-webhook URL in your secret store.
Custom webhook destinations continue receiving the standard batch.completed, batch.failed, or batch.cancelled payloads.
Read the results
Once the batch is terminal, request a page of results:status: "ok" plus http_status, final_url, metadata, and either markdown or html. Failed records have status: "error", error_code, and message. Scrape results echo any submitted itemId and meta.
sample response
limit to keep its payload under approximately 8 MB. Continue based on has_more and next_cursor, not the number of records. Replace CURSOR_FROM_PREVIOUS_RESPONSE with the returned cursor, or set NEXT_CURSOR for cURL:
results.files instead. Each file is gzipped NDJSON. The response includes results.expires_at; retrieve the batch again to obtain fresh links after they expire.
Find previous batches
List batches newest first and combine status, search, and tag filters:q matches batch IDs, crawl sources, and tags. The tags filter matches batches containing any supplied tag. Continue with next_cursor when has_more is true.
Cancel or delete a batch
Cancellation stops new pages from starting. Pages already in progress finish before the batch reachescancelled, and unused reserved credits are released.
completed, cancelled, or failed, you can permanently delete its metadata and stored results:
Handle errors
Batch management has a separate 1,000-unit-per-minute organization limit. A submission uses 50 units; each read, poll, cancellation, or deletion uses 1. See Batch rate limits.Next steps
Build with an agent
Build with an agent
Add batch scraping to your app
Submit a batch
Full request schema, examples, and responses.
Batch results
Paginated success and error records.
Scrape a webpage
Use synchronous scraping for one page at a time.
Best practices
Authentication, retries, caching, and error handling.