# API de SERP em Python: requests, httpx e asyncio

> Use a API de SERP da SerpCrypto em Python: um cliente requests com retentativas, httpx async com limite de concorrência, paginação e exportação em CSV.

- URL: https://serpcrypto.com/pt/docs/python/
- Última atualização: 2026-10-22
- Editor: SerpCrypto (https://serpcrypto.com)

Um cliente reutilizável com retentativas, um loop de paginação que para quando os resultados acabam, pesquisas assíncronas limitadas ao seu limite de concorrência e um CSV diário para rankings. Código para copiar e colar, com sintaxe verificada, sem nenhum pacote nosso para instalar.

**Resposta rápida — Como chamo uma API de SERP em Python?**

Envie uma requisição GET para `https://serpcrypto.com/api/v1/search` com `requests` ou `httpx`, sua chave no header `Authorization: Bearer` e a consulta em `params`, depois leia `response.json()`. **SerpCrypto** cobra 1 crédito por pesquisa bem-sucedida, a partir de US$ 0,30/1K pesquisas, e as retentativas de chamadas com falha são gratuitas. Pague com cripto, sem KYC. O código abaixo precisa apenas de `requests` ou `httpx`.

## Configuração do Python em resumo

| Atributo | Valor |
| --- | --- |
| Instalação | `pip install requests` ou `pip install httpx` |
| Chave | Variável de ambiente `SERPCRYPTO_API_KEY` |
| Header | `Authorization: Bearer <key>` |
| Tempo limite | 60 a 90 segundos: a pesquisa é executada ao vivo |
| Retentativa | Apenas 429, 502 e 504, com backoff; erros são gratuitos |
| Pesquisas em paralelo | Até `concurrency_limit` a partir de `GET /credits` |

## Como configuro um cliente Python reutilizável?

Crie um `requests.Session` com a chave nos headers e uma política de retentativa para os três erros temporários. Uma sessão reutiliza conexões, então um loop de pesquisas gasta menos tempo em handshakes TLS. Salve o arquivo como `serp_client.py`; os próximos exemplos o importam.

`Retry` do urllib3 espera mais antes de cada nova tentativa e respeita um header `Retry-After` se ele for enviado. Ele nunca repete `400`, `401` ou `402`, que precisam de uma correção, não de uma segunda tentativa.

*serp_client.py*

```python
"""serp_client.py: a small, reusable client for the SerpCrypto SERP API (requests)."""
import os

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

API_URL = "https://serpcrypto.com/api/v1/search"
CREDITS_URL = "https://serpcrypto.com/api/v1/credits"


def make_session():
    session = requests.Session()
    session.headers["Authorization"] = "Bearer " + os.environ["SERPCRYPTO_API_KEY"]
    retry = Retry(
        total=4,
        backoff_factor=1.0,  # waits about 1 s, 2 s, 4 s between attempts
        status_forcelist=(429, 502, 504),
        allowed_methods=("GET",),
        respect_retry_after_header=True,
    )
    session.mount("https://", HTTPAdapter(max_retries=retry))
    return session


SESSION = make_session()


def search(q, **params):
    """Run one search (1 credit if it succeeds) and return the parsed JSON."""
    r = SESSION.get(API_URL, params={"q": q, **params}, timeout=90)
    r.raise_for_status()
    return r.json()


def credits():
    """Free: credits left, used today and the concurrency limit."""
    r = SESSION.get(CREDITS_URL, timeout=30)
    r.raise_for_status()
    return r.json()


if __name__ == "__main__":
    data = search("project management software", gl="us", hl="en")
    for item in data.get("organic_results", []):
        print(item["position"], item["link"])
    print(credits())
```

## Como coleto mais de 10 resultados?

Peça as próximas páginas uma a uma. Cerca de 10 resultados orgânicos por página, como o Google vem entregando desde que deixou de respeitar num=100 em setembro de 2025; cada página extra é mais um crédito. Pare assim que `pagination.next_page` estiver ausente: não há mais nada a buscar, e você mantém os créditos.

Para a maior parte do trabalho de rastreamento de ranking, a primeira página ou as três primeiras páginas bastam, porque os cliques se concentram ali. Trinta resultados para uma palavra-chave custam três créditos.

*Paginação: até três páginas, parada antecipada*

```python
from serp_client import search


def top_results(q, pages=3, **params):
    """Collect organic results over several pages: each page is 1 credit."""
    rows = []
    for page in range(1, pages + 1):
        data = search(q, page=page, **params)
        for item in data.get("organic_results", []):
            rows.append({"page": page, "position": item["position"], "title": item["title"], "link": item["link"]})
        if not data.get("pagination", {}).get("next_page"):
            break  # no further page: stop early and save credits
    return rows


rows = top_results("crm for small business", pages=3, gl="gb", hl="en")
print(len(rows), "results")
```

## Como executo muitas pesquisas em paralelo?

Use `httpx.AsyncClient` com um `asyncio.Semaphore` dimensionado para o limite da sua conta. O script lê `concurrency_limit` do endpoint de créditos gratuitos, então ele se adapta quando o suporte aumenta seu limite. Pesquisas acima do limite receberiam `429` de qualquer forma; o semáforo evita desperdiçar essas tentativas.

Cada tarefa repete erros temporários com uma pausa crescente e retorna `None` após quatro falhas, para que uma consulta teimosa nunca bloqueie o lote.

*asyncio + httpx: pesquisas em paralelo dentro do limite*

```python
"""Run many searches in parallel without exceeding the account's concurrency limit."""
import asyncio
import os

import httpx

API_URL = "https://serpcrypto.com/api/v1/search"
CREDITS_URL = "https://serpcrypto.com/api/v1/credits"
HEADERS = {"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]}


async def search_one(client, gate, q):
    async with gate:  # at most N searches at the same time
        for attempt in range(4):
            r = await client.get(API_URL, params={"q": q, "gl": "us", "hl": "en"})
            if r.status_code in (429, 502, 504):
                await asyncio.sleep(2 ** attempt)
                continue
            r.raise_for_status()
            return q, r.json()
        return q, None


async def main(queries):
    async with httpx.AsyncClient(headers=HEADERS, timeout=90) as client:
        limits = (await client.get(CREDITS_URL)).json()
        gate = asyncio.Semaphore(limits["concurrency_limit"])
        results = await asyncio.gather(*(search_one(client, gate, q) for q in queries))
    for q, data in results:
        first = (data or {}).get("organic_results", [{}])[0].get("link")
        print(f"{q!r}: {first}")


asyncio.run(main(["best vpn router", "home espresso machine", "4k monitor for coding"]))
```

## Como salvo os rankings diários em um arquivo CSV?

Acrescente uma linha por resultado, com o dia, a palavra-chave, a posição, o link e as configurações que a API aplicou. Ler `gl` e `device` de `search_parameters` em vez das suas próprias variáveis faz o arquivo registrar o que foi realmente usado.

Execute o script uma vez por dia com cron ou com o Agendador de Tarefas do Windows. Três palavras-chave no mobile custam três créditos por dia, cerca de 90 por mês.

*Acrescentar os rankings de hoje ao rankings.csv*

```python
import csv
from datetime import date

from serp_client import search

KEYWORDS = ["standing desk", "ergonomic chair", "monitor arm"]
FIELDS = ["day", "keyword", "position", "title", "link", "gl", "device"]

with open("rankings.csv", "a", newline="", encoding="utf-8") as fh:
    writer = csv.DictWriter(fh, fieldnames=FIELDS)
    if fh.tell() == 0:
        writer.writeheader()
    for kw in KEYWORDS:
        data = search(kw, gl="gb", hl="en", device="mobile")
        applied = data["search_parameters"]
        for item in data.get("organic_results", []):
            writer.writerow({
                "day": date.today().isoformat(),
                "keyword": kw,
                "position": item["position"],
                "title": item["title"],
                "link": item["link"],
                "gl": applied["gl"],
                "device": applied["device"],
            })
```

## Qual cliente HTTP em Python devo usar?

Use `requests` para scripts e cron jobs: é simples e seu adaptador de retry é maduro. Use `httpx` quando precisar de código assíncrono, como um web app, um agente ou um lote de centenas de palavras-chave. Ambos enviam a mesma requisição e recebem o mesmo JSON; a API não se importa com qual deles você escolhe.

Evite timeouts muito curtos com qualquer uma das bibliotecas. Um cliente que desiste depois de cinco segundos pode reenviar uma pesquisa que ainda estava rodando e pagar pelas duas.

## Quanto vai custar meu script?

Conte pesquisas, não resultados: uma chamada é um crédito quando dá certo. Um job de 500 palavras-chave, uma página cada, todos os dias por 30 dias, são 15.000 pesquisas. No pack 25.000 pesquisas (US$ 18,75) isso deixa folga de sobra, e Os créditos de pesquisa pré-pagos nunca expiram: as pesquisas não utilizadas ficam na sua conta até você usá-las.

Confira o saldo pelo código com o helper `credits()` acima; isso não custa nada.

## Perguntas sobre Python

### Existe um pacote SerpCrypto no PyPI?

Não. Os exemplos chamam o endpoint HTTPS com `requests` ou `httpx`, duas bibliotecas amplamente usadas, então não há nada nosso para instalar ou atualizar. O cliente acima tem cerca de 40 linhas e é seu.

### Quais versões do Python este código suporta?

Python 3.9 e superiores. O exemplo assíncrono usa `asyncio.run`, disponível desde o Python 3.7, e o restante usa apenas a biblioteca padrão mais `requests` ou `httpx`.

### Posso usar a API a partir de um notebook Jupyter?

Sim. Defina `SERPCRYPTO_API_KEY` antes de iniciar o Jupyter, ou leia a chave com `getpass` dentro do notebook para que ela não acabe em uma célula salva. Em um notebook, use `await main(...)` em vez de `asyncio.run(main(...))`.

### Como transformo os resultados em um DataFrame do pandas?

Passe a lista de dicionários de resultado para `pandas.DataFrame(data["organic_results"])`. Cada campo vira uma coluna; campos opcionais ausentes, como `date`, viram células vazias.

---

SerpCrypto: O SerpCrypto é uma API de SERP para desenvolvedores e agentes de IA que retorna resultados de pesquisa do Google e do Bing em JSON, pago com cripto e sem envio de documento de identidade. Os créditos de pesquisa pré-pagos a partir de US$ 0,30/1K pesquisas nunca expiram. Sem KYC — sem documento, sem selfie, sem documentos. Pague com cripto.
