# Google Search API with Python

> This example uses only the Python standard library. It sends a JSON request, checks the HTTP response, and returns ordered organic results.

gsearch.dev is an independent service and is not affiliated with or endorsed by Google.

## Copy the complete Python example

Set GSEARCH_API_KEY in your server environment before running the code. Do not paste a real key into the source file.

### Python 3

```python
import json
import os
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen

def read_json(stream):
    try:
        body = json.load(stream)
    except (UnicodeDecodeError, json.JSONDecodeError):
        return None
    return body if isinstance(body, dict) else None

payload = json.dumps({
    "q": "Ada Lovelace",
    "gl": "us",
    "hl": "en",
    "page": 1,
}).encode("utf-8")

request = Request(
    "https://gsearch.dev/api/v1/search",
    data=payload,
    headers={
        "Content-Type": "application/json",
        "X-API-Key": os.environ["GSEARCH_API_KEY"],
    },
    method="POST",
)

try:
    with urlopen(request, timeout=10) as response:
        result = read_json(response)
        if result is None or not isinstance(result.get("organic"), list):
            raise RuntimeError("The search API returned an invalid JSON response")
        for item in result["organic"]:
            print(item["position"], item["title"], item["link"])
except HTTPError as error:
    body = read_json(error) or {}
    details = body.get("error", {})
    code = details.get("code", "SEARCH_FAILED")
    message = details.get("message", "Search request failed")
    request_id = details.get("requestId", "no request ID")
    raise RuntimeError(f"{error.code}: {code} {message} ({request_id})") from error
except URLError as error:
    raise RuntimeError("The search request could not connect") from error
```

## Use the response fields directly

The organic array is ordered by position. Each item contains title, link, snippet, and position. The response also includes resultCount, cached, normalized searchParameters, and requestId.

Use dictionary access for required fields and get for optional diagnostic text. Keep requestId when logging an error or asking for support.

## Add production safeguards

The example sets a 10 second network timeout. In a web application, also cap retries and map upstream failures to a simple error for your users.

- Reuse HTTPS connections through your application HTTP client when request volume grows.
- Retry temporary rate-limit and service errors with increasing delays.
- Never include the API key in logs or error messages.
- Validate q, gl, hl, and page before sending user input.

## Know when a credit is used

One successful response uses one search credit, including a cached response. Failed requests do not use a credit. The Free plan includes 100 searches each calendar month.

## Next steps

- [Review the JSON guide](https://gsearch.dev/guides/google-search-results-json/index.md): Understand localization, result fields, credits, and retry behavior.
- [See the Node.js example](https://gsearch.dev/integrations/nodejs/index.md): Use the same API contract with the built-in fetch function.
- [Compare plans](https://gsearch.dev/pricing): Check monthly credits, rate limits, and annual prices.
- [Complete API documentation](https://gsearch.dev/docs): Authentication, fields, supported values, limits, responses, and errors.
- [OpenAPI 3.1 specification](https://gsearch.dev/openapi.json): Machine-readable public API contract.
