Reserp Python SDK
The official minimal Python client for Reserp v2, a Google Search API with two response shapes:
urls()/search()callsPOST /v2/serp/urlsfor a flat, page-ordered, deduplicated URL-and-text index.structured()callsPOST /v2/serp/structuredfor typed result families, SERP features, and explicit positions.
Website · API documentation · OpenAPI 3.1 · Postman · Pricing
Design
Each SDK call makes exactly one API request and returns the native httpx.Response unchanged. The package adds no retry, timeout, URL-building, validation, pagination, transformation, cache, batch, queue, or concurrency policy. Typed dictionaries describe both public v2 contracts without changing them at runtime.
Installation
pip install reserp
Python 3.10 or later is required.
URL index
import os
from reserp import Reserp
with Reserp(api_key=os.environ["RESERP_API_KEY"]) as reserp:
response = reserp.urls(
{"url": "https://www.google.com/search?q=best+pizza+in+dubai&gl=ae&hl=en"}
)
data = response.json()
if data["ok"]:
for item in data["urls"]:
print(item.get("text"), item["url"])
else:
print(response.status_code, data["error"], data["retryable"], data["billed"])
search() is an alias for urls() and also uses the v2 URL-index endpoint.
Structured results
with Reserp(api_key=os.environ["RESERP_API_KEY"]) as reserp:
response = reserp.structured(
{"url": "https://www.google.com/search?q=wireless+earbuds&gl=us&hl=en&tbm=shop"}
)
data = response.json()
if data["ok"]:
for result in data["results"]["organic"]:
print(result["position"], result["title"], result["url"])
for feature in data["features"]:
print(feature["page_position"], feature["type"])
Async client
import asyncio
import os
from reserp import AsyncReserp
async def main() -> None:
async with AsyncReserp(api_key=os.environ["RESERP_API_KEY"]) as reserp:
response = await reserp.urls(
{"url": "https://www.google.com/search?q=photonic+computing&gl=us&hl=en"}
)
print(response.status_code, response.json())
asyncio.run(main())
Native transport control
Inject an HTTPX client for transport policy and pass request options directly to the matching client method:
import httpx
limits = httpx.Limits(max_connections=50, max_keepalive_connections=20)
timeout = httpx.Timeout(20.0)
with httpx.Client(limits=limits, timeout=timeout) as transport:
reserp = Reserp(api_key=os.environ["RESERP_API_KEY"], client=transport)
response = reserp.urls(
{"url": "https://www.google.com/search?q=semiconductors&gl=us&hl=en&tbs=qdr:w"},
headers={"x-request-id": "your-job-id"},
follow_redirects=False,
)
Transport failures remain native HTTPX exceptions. HTTP error responses remain native responses; inspect their status, headers, and JSON body.
Direct HTTP equivalents
curl https://api.reserp.ai/v2/serp/urls \
--request POST \
--header "Authorization: Bearer $RESERP_API_KEY" \
--header "Content-Type: application/json" \
--data '{"url":"https://www.google.com/search?q=photonic+computing&gl=us&hl=en"}'
curl https://api.reserp.ai/v2/serp/structured \
--request POST \
--header "Authorization: Bearer $RESERP_API_KEY" \
--header "Content-Type: application/json" \
--data '{"url":"https://www.google.com/search?q=photonic+computing&gl=us&hl=en"}'
Pagination and errors
Every successful response contains pagination.next_url. Send that URL back as the next request body's url; its presence does not guarantee that another page contains results. Do not calculate pagination from len(data["urls"]) or a structured result-family length.
Error bodies expose error, retryable, billed, and billing_source. If your application retries, use retryable as the authority and honor Retry-After on HTTP 429. The SDK never retries automatically.
Migrating from v1
For URL-and-text workflows, replace the v1 recursive results[] tree with v2 urls[]. Other notable renames are url → request.url, finalUrl → page.url, pagination.nextUrl → pagination.next_url, and billingSource → billing_source. Ranking and SERP-analysis workflows should use structured() and the appropriate typed result family.
License
MIT
Metadata
Release files for reserp 0.3.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 | |
|---|---|---|---|
| reserp-0.3.0.tar.gz | 70.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| reserp-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 77.9 kB
Release files / reserp-0.3.0.tar.gz
| Download URL | reserp-0.3.0.tar.gz |
|---|---|
| Size | 70.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e3254282ca03532513d01a0a9ba8d1d36b8dfef7ac55c78843d4b9d7b5fac473
|
|
BLAKE2b-256 checksum How to use checksums |
081636f11cc26e570f3added71afa5e72c6b87bcdb73c126f947e49c04b3e113
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / reserp-0.3.0-py3-none-any.whl
| Download URL | reserp-0.3.0-py3-none-any.whl |
|---|---|
| Size | 7.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fc0945cb78b1e86dc8aa14c025da6253b31d975b755ffede902b832d95be5d9a
|
|
BLAKE2b-256 checksum How to use checksums |
463751e67add0425b458ebf5c50169e07f080dc9b923301b3e8f77fe9816344f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|