Reserp Python SDK
The official minimal Python client for Reserp v2, a Google Search API with two stable response shapes:
search()callsPOST /v2/serp/searchfor flat, page-ordered, deduplicated results inresults[].structured()callsPOST /v2/serp/structuredfor best-effort extraction of typed, page-ordered SERP blocks inblocks[].
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 generated from the canonical schema describe both v2 contracts without changing them at runtime.
Installation
pip install reserp
Python 3.10 or later is required.
Search results
import os
from reserp import Reserp
with Reserp(api_key=os.environ["RESERP_API_KEY"]) as reserp:
response = reserp.search(
{"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["results"]:
print(item.get("text"), item["url"])
else:
print(response.status_code, data["error"], data["retryable"], data["billed"])
The deprecated urls() method is a compatibility alias for search() and uses the stable Search 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 block in data["blocks"]:
print(block["position"], block["type"], block["title"])
if block["type"] == "organic":
for item in block["items"]:
print(item["position"], item["title"], item["url"])
Detailed block and item types are available from reserp.types.
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.search(
{"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.search(
{"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/search \
--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["results"]), len(data["blocks"]), or any block's item count.
Error bodies expose error, message, doc_url, retryable, billed, and billing_source. Use message and doc_url for diagnostics; message wording may change, so branch on the stable error code and retryable flag. If your application retries, use retryable as the authority and honor Retry-After on HTTP 429. The SDK never retries automatically.
Migrating
From SDK 0.3, replace urls() with search(), /v2/serp/urls with /v2/serp/search, and data["urls"] with data["results"]. urls() remains as a deprecated method alias, but its response now follows the stable Search contract.
If you used the structured beta, replace schema_version, grouped results, features, page_position, and metadata with the stable, page-ordered blocks[] model. Each block has type and position; block-specific entries live in items[].
When migrating directly from v1, other notable renames are url → request.url, finalUrl → page.url, pagination.nextUrl → pagination.next_url, and billingSource → billing_source.
License
MIT
Metadata
Release files for reserp 0.4.1
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.4.1.tar.gz | 71.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| reserp-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 80.7 kB
Release files / reserp-0.4.1.tar.gz
| Download URL | reserp-0.4.1.tar.gz |
|---|---|
| Size | 71.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8484c15a8d33ff619b79a6a94eb5df63c6539e7c5e448c4b1cace31b3fdef4c5
|
|
BLAKE2b-256 checksum How to use checksums |
7a664049cb5c704057f1e2a055b0fd5d9cf6186177d10ca0b16742009ddd6611
|
| 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.4.1-py3-none-any.whl
| Download URL | reserp-0.4.1-py3-none-any.whl |
|---|---|
| Size | 8.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
22fac5aa10720a68ac633289829f427bee24a0ded96ffc1b28bc04f05c3f7a91
|
|
BLAKE2b-256 checksum How to use checksums |
36eafaf2d6292bba1efa6dd2403148b6b95b68fc3b0ee71170b379b81b7a6ed1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|