webscrape-ai (Python)
Official Python SDK for the webscrape.ai web scraping API. Fetch pages, run LLM structured extraction, and dispatch/poll SmartBrowse recipe replays — with typed responses, an ergonomic error hierarchy, and automatic, billing-safe retries.
- Sync
Clientand asyncAsyncClient(both context managers) - Frozen dataclass responses, fully type-hinted, ships
py.typed - One runtime dependency:
httpx - Python 3.10+
Install
pip install webscrape-ai
Authentication
Every request sends your API key in the X-API-Key header. Provide it explicitly
or via the WEBSCRAPE_API_KEY environment variable (the client reads it at
construction and fails fast if neither is set):
from webscrape_ai import Client
client = Client(api_key="wsg_live_...") # or: Client() → reads WEBSCRAPE_API_KEY
Get a key from the dashboard. Format:
wsg_live_<32 base62 chars>.
Quickstart
Scrape a page
from webscrape_ai import Client
with Client() as client:
resp = client.scrape(website_url="https://example.com", clean=True)
print(resp.data.html) # cleaned markdown
print(resp.credits_used, resp.credits_remaining)
print(resp.request_id) # support-facing envelope id (req_...)
print(resp.data.request_id) # extraction id (distinct from the top-level request_id)
Structured extraction with smartscraper
schema = {
"type": "object",
"properties": {
"stories": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"url": {"type": "string"},
"score": {"type": "integer"},
},
},
}
},
}
with Client() as client:
resp = client.smartscraper(
website_url="https://news.ycombinator.com",
user_prompt="Extract the front-page stories with title, url, and score.",
output_schema=schema,
)
print(resp.data.result) # schema-shaped dict (Any)
SmartBrowse: dispatch a run and wait for it
from webscrape_ai import Client, RunFailedError, WaitTimeoutError
with Client() as client:
try:
run = client.smartbrowse.run_and_wait("m3Yc2tFvN8q", timeout=900)
print(run.data.run_status) # RunStatus.COMPLETED
print(run.data.pages_extracted, run.data.credits_used)
for page in (run.data.result.pages or []):
for item in (page.items or []):
print(item)
except RunFailedError as e:
print("run failed:", e.run.data.error)
except WaitTimeoutError as e:
print("still running at deadline:", e.run.data.run_status)
# Or drive the loop yourself:
dispatch = client.smartbrowse.run("m3Yc2tFvN8q")
run = client.smartbrowse.get_run(dispatch.data.run_id)
usage = client.smartbrowse.usage()
print(usage.data.runs_used_30d, "/", usage.data.runs_per_month_cap)
Async
Every method is mirrored on AsyncClient:
import asyncio
from webscrape_ai import AsyncClient
async def main():
async with AsyncClient() as client:
resp = await client.scrape(website_url="https://example.com", clean=True)
print(resp.data.html)
run = await client.smartbrowse.run_and_wait("m3Yc2tFvN8q")
print(run.data.run_status)
asyncio.run(main())
Error handling
Error envelopes are raised as typed exceptions, all rooted at WebscrapeError.
Branch on the subtype (never on the human-readable message):
from webscrape_ai import (
Client,
AuthenticationError,
InsufficientCreditsError,
RateLimitError,
ValidationError,
NotFoundError,
APIError,
)
with Client() as client:
try:
resp = client.smartscraper(
website_url="https://example.com",
user_prompt="Extract the product price.",
)
except InsufficientCreditsError as e:
print(f"need {e.required}, have {e.balance}")
except RateLimitError as e:
print("throttled:", e.reason) # rate_limit_per_min | max_concurrent_requests | sb_runs_per_month
except AuthenticationError:
print("bad or missing API key")
except ValidationError as e:
print("extraction failed validation:", e.details)
except NotFoundError:
print("no such resource")
except APIError as e:
# Any other (or brand-new) error code lands here; the raw code is preserved.
print(e.status_code, e.code, e.message, e.request_id)
Exception families (subtypes of APIError unless noted):
| Exception | Error code(s) |
|---|---|
AuthenticationError |
unauthorized |
InsufficientCreditsError |
insufficient_credits (.balance, .required) |
EmailVerificationError |
email_verification_required |
ForbiddenError |
forbidden |
NotFoundError |
not_found |
ConflictError |
conflict, account_deletion_pending (.deletion_scheduled_for) |
BadRequestError |
invalid_request |
ValidationError |
validation_failed |
RateLimitError |
rate_limited (.reason) |
ServerError |
internal_error, service_unavailable |
APIError |
any unknown code (raw .code preserved) |
TransportError / APITimeoutError |
network failure / timeout (not HTTP) |
ConfigurationError |
missing API key at construction |
RunFailedError / WaitTimeoutError |
terminal-failed run / wait deadline (carry .run) |
Configuration
| Option | Default | Notes |
|---|---|---|
api_key |
WEBSCRAPE_API_KEY env var |
fails fast if neither set |
base_url |
https://api.webscrape.ai/v1 |
override for self-hosted / staging |
timeout |
180.0 seconds |
per request |
max_retries |
2 |
up to 3 attempts; 0 disables |
http_client |
new httpx.Client / httpx.AsyncClient |
pass your own to customize transport, proxies, TLS |
Retries are automatic and billing-safe: only 429/500/502/503 and
connection-establishment failures are retried (exponential backoff, full jitter,
capped at 30s; Retry-After honored if present). Other 4xx are never retried.
Docs
Full API reference: https://webscrape.ai/docs
License
MIT
Release files for webscrape-ai 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| webscrape_ai-0.1.0.tar.gz | 14.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| webscrape_ai-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.5 kB
Release files / webscrape_ai-0.1.0.tar.gz
| Download URL | webscrape_ai-0.1.0.tar.gz |
|---|---|
| Size | 14.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1285927494b193dba623ed7a219343843715d73d62f2826a944d907539786a90
|
|
BLAKE2b-256 checksum How to use checksums |
95a4682894931c5e99262ebb294add57dba9c3860ef00fdda958632f2ab5bfb5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 7, 2026.
Transparency logRelease files / webscrape_ai-0.1.0-py3-none-any.whl
| Download URL | webscrape_ai-0.1.0-py3-none-any.whl |
|---|---|
| Size | 18.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9d0a80cab5c80cf2462bcc8259ad0199bc9b16f2f29d344635419a715fd2531c
|
|
BLAKE2b-256 checksum How to use checksums |
01e66dc33cea82d9ee5c60cfe7d82fc78df9cb42e0db270256d7df1851db0e59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 7, 2026.
Transparency log