Skip to main content

Reserp Google Search API

Reserp Python SDK

PyPI version Python versions CI License: MIT

Google Search data, structured for scale.

The official minimal Python client for Reserp, a high-yield Google Search API and SERP API for high-volume, recurring production search workloads.

Reserp returns visible Google Search result blocks as structured JSON, including organic listings, news, carousels, sitelinks, pagination, and nested results in Google's response order. Start for free with no credit card required.

Website · API documentation · OpenAPI 3.1 · Postman · Pricing

Design

This package is a transparent wrapper over POST /v1/serp:

  • One client call sends exactly one API request.
  • The request dictionary is the public API request body.
  • The return value is the native httpx.Response.
  • Status codes, response headers, success payloads, and error payloads remain unchanged.
  • Native HTTPX request options and caller-configured sync or async clients pass through.
  • Typed dictionaries describe the public API contract without changing it at runtime.

The client does not retry, back off, impose its own timeouts, build or validate Google URLs, follow pagination, transform responses, cache data, batch work, or control concurrency. Those decisions remain with the caller and the configured HTTPX transport.

Installation

pip install reserp

Python 3.10 or later is required.

Quick start

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 not data["ok"]:
        print(response.status_code, data["error"], data["retryable"], data["billed"])
    else:
        for result in data["results"]:
            print(result.get("text"), result.get("url"))

Create an API key in the Reserp dashboard. Keep API keys on your server; never embed one in browser or mobile code.

Production workloads at scale

For bulk Google Search, recurring SERP collection, SEO monitoring, market intelligence, competitive research, and other business-critical data pipelines, place the API behind infrastructure that owns durability and throughput:

producer -> durable queue -> workers with controlled concurrency -> Reserp API

Use Cloud Tasks, SQS, BullMQ, Celery, or an equivalent durable queue. Let one layer own retries and backoff, bound worker concurrency, respect Retry-After, persist job state and results, and design for possible duplicate queue delivery. These practices are identical whether a worker uses this transparent client or direct HTTP.

Native transport control

Use an HTTPX client to control transport behavior without an SDK policy layer:

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=semiconductor+manufacturing&gl=us&hl=en&tbs=qdr:w"
        },
        headers={"x-request-id": "your-job-id"},
        follow_redirects=False,
    )

Additional non-conflicting keyword arguments are passed to httpx.Client.post or httpx.AsyncClient.post after the SDK supplies the endpoint, authorization header, content type, and JSON body. If you do not inject a client, normal HTTPX transport defaults apply.

Transport and timeout failures remain native HTTPX exceptions. HTTP error responses do not become SDK exceptions; inspect the native status, headers, and API JSON body.

Async client

import asyncio
import os

import httpx
from reserp import AsyncReserp


async def main() -> None:
    async with httpx.AsyncClient() as transport:
        reserp = AsyncReserp(
            api_key=os.environ["RESERP_API_KEY"],
            client=transport,
        )
        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())

Direct HTTP equivalent

The client call is equivalent to this direct API request:

curl https://api.reserp.ai/v1/serp \
  --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"}'

Use either interface according to your application. Both expose the same Google Search API contract and leave workload behavior under your control.

Results and pagination

Each result block may contain text, url, and children. text is optional: it is omitted when the block has no visible text. When present, it is a non-empty string containing visible text joined with newlines.

Pagination uses Google's organic-result offset, not the number of URLs in results. A response can contain URLs from many visible result types—including organic listings, news, carousels, sitelinks, and nested result blocks—so never derive the next offset from len(data["results"]).

The start parameter selects the page by organic-result offset. Omit it or use 0 for the first page, 10 for the second, 20 for the third, and continue in increments of 10. Any other value returns a non-billable 400 invalid_request response.

Clients fetching pages independently or asynchronously can set start directly in each submitted Google Search URL:

with Reserp(api_key=os.environ["RESERP_API_KEY"]) as reserp:
    third_page_response = reserp.search(
        {"url": "https://www.google.com/search?q=photonic+computing&gl=us&hl=en&start=20"}
    )
    third_page = third_page_response.json()

pagination.nextUrl is provided as a convenience for clients advancing sequentially from a completed response:

with Reserp(api_key=os.environ["RESERP_API_KEY"]) as reserp:
    first_response = reserp.search(
        {"url": "https://www.google.com/search?q=photonic+computing&gl=us&hl=en"}
    )
    first_page = first_response.json()

    if first_page["ok"]:
        next_response = reserp.search({"url": first_page["pagination"]["nextUrl"]})
        next_page = next_response.json()

Standard Google Search parameters such as q, gl, hl, tbm, and tbs belong in the submitted Google URL. See the API documentation for the authoritative request contract.

Errors and billing signals

API errors use stable JSON fields:

{
  "ok": false,
  "error": "rate_limited",
  "retryable": true,
  "billed": false
}

The API response is authoritative. Automatically retry only when retryable is true. For 429, wait for the number of seconds in Retry-After; for other retryable errors, use exponential backoff with jitter. billed only confirms whether billing settled before the error response; it does not override retryable. Avoid blindly retrying an ambiguous transport failure whose billing outcome is unknown. The client does not make those decisions.

API resources

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

reserp-0.2.3.tar.gz (9.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reserp-0.2.3-py3-none-any.whl (7.7 kB view details)

Uploaded Python 3

File details

Details for the file reserp-0.2.3.tar.gz.

File metadata

  • Download URL: reserp-0.2.3.tar.gz
  • Upload date:
  • Size: 9.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for reserp-0.2.3.tar.gz
Algorithm Hash digest
SHA256 b5b08bf903a05c8f74fa85e329a24c316626f72d0c3ead333bca30628f7c4f14
MD5 233be4bd731c404498e0d840b5031f51
BLAKE2b-256 a1ae949bf099199c7644368e91b243c73e566c30934c42dad04bd40613731926

See more details on using hashes here.

File details

Details for the file reserp-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: reserp-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 7.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for reserp-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 ccb0860ef308498c8ebae257848bc3fce5dddfb1dc89a27382b1d7842b9a85be
MD5 f1179b460c50db3428042b06208a05d2
BLAKE2b-256 635024c2f01d11f818247109768da69256030de0aac0a28280669d9880119549

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page