Python SDK
Official Python client for ByteKit, with sync and async support.
For AI agents: https://bytekit.com/llms.txt — every docs page is available as markdown by appending .md
The official Python SDK is generated from the ByteKit OpenAPI spec, so its models and
methods always match the API. ByteKit is a thin client on top of it for everyday use; the
generated operations underneath ship in both synchronous and asynchronous form.
Install
pip install bytekit-sdkThe PyPI distribution is bytekit-sdk; the import name is bytekit.
Your first scrape
from bytekit import ByteKit
client = ByteKit(api_key="sk_live_your_api_key_here")
result = client.scrape.create(url="https://example.com", formats=["markdown"])
print(result.formats.markdown)result is the parsed ScrapeSuccessEnvelope. Request fields are keyword arguments under the
API's own field names, with plain JSON values, so formats=["markdown"] needs no enum import.
Only the fields you pass are sent.
Handle errors
Any non-2xx response raises ByteKitError, as does a scrape.create call that comes back as
HTTP 200 with a failed envelope. So does a response the generated operation cannot turn into a
documented model: an undocumented status (even a 2xx), a body that is not JSON, or a body that
does not match the documented shape. It carries the HTTP status_code and the API's code and
message (both None when the body is not an error envelope):
import httpx
from bytekit import ByteKit, ByteKitError
client = ByteKit(api_key="sk_live_your_api_key_here")
try:
client.scrape.create(url="https://example.com")
except ByteKitError as err:
print(err.status_code, err.code, err.message)
except httpx.HTTPError:
print("Could not reach the API") # connection refused, DNS failure, timeout, ...ByteKitError subclasses bytekit.errors.UnexpectedStatus, so code that already catches that
keeps working. A transport failure is not wrapped: it propagates as the httpx exception.
Async scrapes
Pass async_=True to get a queued receipt back and poll it by ID. A 202 is returned, not
raised:
queued = client.scrape.create(url="https://example.com", async_=True)
job = client.scrape.get(queued.id)scrape.get returns the job's envelope as it stands, so a job that ended in failure comes back
as a ScrapeErrorEnvelope rather than raising.
Other resources
Every API operation is a method on the client, grouped by resource. Path IDs are the first
positional argument, query parameters are keywords (limit=5, status="completed"), and every
other keyword is a request-body field. Pass body fields as keywords, not as a body= argument
(that raises TypeError). A string for an enum-valued query parameter is converted, and one that
is not a valid value raises ValueError.
| Resource | Methods |
|---|---|
account | get |
bulk | create, get, delete, list_screenshots |
fetch | create, get |
fetch_bulk | create, get |
monitors | create, list, get, update, delete, list_captures |
scrape | create, get |
scrape_bulk | create, get |
screenshots | create, get |
search | create |
sitemap | create, get |
usage | get, get_daily, get_by_endpoint |
webhooks | list_deliveries, retry_delivery |
Parameters keep the generated spelling: from_ on usage.get_daily and
usage.get_by_endpoint, async_ on scrape.create and screenshots.create, and url_query
(the url query parameter) on fetch.get. Date parameters take objects, not strings:
datetime.date for from_ and to on the usage methods, datetime.datetime for since on
webhooks.list_deliveries.
The generated client
ByteKit calls the generated operations in bytekit.api.*, which you can use directly when you
want the typed request models and the full response:
from bytekit import AuthenticatedClient
from bytekit.api.scrape import create_scrape
from bytekit.models.scrape_request import ScrapeRequest
from bytekit.models.scrape_request_formats_item import ScrapeRequestFormatsItem
from bytekit.models.scrape_success_envelope import ScrapeSuccessEnvelope
client = AuthenticatedClient(
base_url="https://api.bytekit.com",
token="sk_live_your_api_key_here",
)
body = ScrapeRequest(
url="https://example.com",
formats=[ScrapeRequestFormatsItem.MARKDOWN],
)
response = create_scrape.sync(client=client, body=body)
# A documented error status (400, 429, 500, ...) comes back as an `Error` model, and a queued
# receipt as a ScrapeQueuedEnvelope. Only a ScrapeSuccessEnvelope carries populated formats.
if isinstance(response, ScrapeSuccessEnvelope) and isinstance(response.formats.markdown, str):
print(response.formats.markdown)
else:
print(f"Scrape not complete: {response}")Each operation exposes four call styles:
create_scrape.sync(...)— returns the parsed model.create_scrape.sync_detailed(...)— returns the fullResponse(status code, headers, body).create_scrape.asyncio(...)— awaitable form ofsync.create_scrape.asyncio_detailed(...)— awaitable form ofsync_detailed.
What a call does with a response it cannot turn into a documented model depends on the client's
raise_on_unexpected_status, which defaults to True:
- An undocumented status, a body that is not JSON or does not match the documented shape, or a
200scrape carrying thefailedenvelope raisesbytekit.errors.UnexpectedStatus(withstatus_code,codeandmessage). syncandasyncioreturnNonefor those only when you construct the client withraise_on_unexpected_status=False.- A transport failure never returns
None: it raises thehttpxexception.
Async usage
import asyncio
from bytekit import AuthenticatedClient
from bytekit.api.screenshots import create_screenshot
from bytekit.models.screenshot_request import ScreenshotRequest
async def main():
client = AuthenticatedClient(
base_url="https://api.bytekit.com",
token="sk_live_your_api_key_here",
)
body = ScreenshotRequest(url="https://example.com")
response = await create_screenshot.asyncio(client=client, body=body)
print(response)
asyncio.run(main())Reference
The Python SDK Reference covers the generated client classes and operations
by resource. ByteKit and ByteKitError are documented on this page.
Next steps
- TypeScript SDK — the same API surface in TypeScript.
- API Reference — the underlying REST endpoints.
- Errors — error codes and retry guidance.