Quickstart
Make your first ByteKit API call in under 5 minutes — no SDK required.
Nothing to install. You only need curl and an API key.
Get an API key
Sign up at app.bytekit.com and create an API key from the
dashboard. Keys are prefixed sk_live_.
See Authentication for details on key formats and management.
Make your first scrape
Set your API key and run this — no file to save, no chmod:
curl -X POST https://api.bytekit.com/v1/scrape \
-H "Authorization: Bearer $BYTEKIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'Want a full-featured script with error handling and jq formatting? Use this instead:
#!/usr/bin/env bash
# POST /v1/scrape — scrape a URL and return its content as markdown.
# Usage: BYTEKIT_API_KEY=sk_... bash examples/curl/scrape.sh
set -euo pipefail
: "${BYTEKIT_API_KEY:?BYTEKIT_API_KEY is required}"
BASE_URL="${BYTEKIT_BASE_URL:-https://api.bytekit.com}"
curl -sf -X POST "$BASE_URL/v1/scrape" \
-H "Authorization: Bearer $BYTEKIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "formats": ["markdown"]}' \
| jq .A successful response looks like this — every envelope field is snake_case:
{
"schema_version": 1,
"status": "success",
"id": "sc_84c14b1058184045b97ae360ad74888b",
"url": "https://example.com",
"final_url": "https://example.com",
"content_type": "text/html",
"content_length": 318,
"status_code": 200,
"retrieved_at": "2026-08-27T12:16:01.872Z",
"formats": {
"raw": "<!doctype html><html lang=\"en\"><head><title>Example Domain</title>…</html>\n"
},
"metadata": {
"title": "Example Domain",
"description": null,
"language": "en",
"canonicalUrl": null,
"ogTitle": null,
"ogDescription": null,
"ogImage": null,
"ogUrl": null,
"ogSiteName": null,
"robots": null,
"byline": null,
"publishedAt": null
},
"cache": "miss",
"billing": {
"raw_bytes": 318,
"factors": [{ "name": "endpoint", "value": 1, "reason": "scrape" }],
"multiplier": 1,
"billed_bytes": 318
}
}content_length is the compressed wire size in bytes (used for bandwidth billing), and
billing breaks down what the request actually cost. cache is "miss" or "hit", and a
hit adds a cache_age_s field. The id field uses the sc_ prefix — you can poll
GET /v1/scrape/{id} if the scrape was queued asynchronously.
The keys inside metadata stay camelCase (canonicalUrl, ogTitle, …): they are the
page's own metadata, not envelope fields.
Ask for markdown
The default format is raw — that is why the response above carries no
formats.markdown. Request markdown explicitly:
curl -X POST https://api.bytekit.com/v1/scrape \
-H "Authorization: Bearer $BYTEKIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","formats":["markdown"]}'Markdown output is billed at 1.5× the request's upstream wire bytes — the endpoint
factor in the billing node below is the rate your balance is charged, not a display
weighting. See Bandwidth billing for how the factors compose.
The response's formats object is keyed by what you asked for:
{
"schema_version": 1,
"status": "success",
"id": "sc_f659fa67dfb244159767132c2aa50917",
"url": "https://example.com",
"final_url": "https://example.com",
"content_type": "text/html",
"content_length": 318,
"status_code": 200,
"retrieved_at": "2026-08-27T12:16:11.337Z",
"formats": {
"markdown": "---\ntitle: \"Example Domain\"\nurl: \"https://example.com\"\ncaptured_at: \"2026-08-27T12:16:11.416Z\"\n---\nThis domain is for use in documentation examples without needing permission. Avoid use in operations.\n\n[Learn more](https://iana.org/domains/example)"
},
"metadata": {
"title": "Example Domain",
"description": null,
"language": "en",
"canonicalUrl": null,
"ogTitle": null,
"ogDescription": null,
"ogImage": null,
"ogUrl": null,
"ogSiteName": null,
"robots": null,
"byline": null,
"publishedAt": null
},
"cache": "hit",
"cache_age_s": 8,
"billing": {
"raw_bytes": 318,
"factors": [
{ "name": "endpoint", "value": 1.5, "reason": "scrape_md" },
{ "name": "cache_hit", "value": 0.5, "reason": "hit, age 8s" }
],
"multiplier": 0.75,
"billed_bytes": 239
}
}See Scraping for the other formats (markdown, links, images).
Prefer an SDK?
Skip the raw HTTP and use an official client:
- TypeScript SDK —
npm install @hunt-labs/bytekit-sdk - Python SDK —
pip install bytekit-sdk
Next steps
- Authentication — key formats, Bearer header, self-serve key management
- Scraping — formats, options, latency, and async polling
- Errors — error shape, common codes, retry guidance
- Rate Limits — quota model, concurrency slots, rate limit headers
- Monitors — page-change detection (screenshot or scrape) with webhook notifications
- API Reference — full endpoint documentation