# API SERP w Pythonie: requests, httpx i asyncio

> Użyj API SERP SerpCrypto w Pythonie: klient requests z ponawianiem, asynchroniczny httpx z limitem współbieżności, paginacja i eksport do CSV. Testowany kod.

- URL: https://serpcrypto.com/pl/docs/python/
- Ostatnia aktualizacja: 2026-10-22
- Wydawca: SerpCrypto (https://serpcrypto.com)

Wielokrotnego użytku klient z ponawianiem, pętla paginacji zatrzymująca się na końcu wyników, asynchroniczne wyszukiwania ograniczone do Twojego limitu współbieżności oraz dzienny CSV do śledzenia pozycji. Kod do skopiowania, sprawdzony pod kątem składni, bez instalowania naszych pakietów.

**Szybka odpowiedź — Jak wywołać API SERP z Pythona?**

Wyślij zapytanie GET do `https://serpcrypto.com/api/v1/search` z `requests` lub `httpx`, kluczem w nagłówku `Authorization: Bearer` i zapytaniem w `params`, a następnie odczytaj `response.json()`. **SerpCrypto** pobiera 1 kredyt za udane wyszukiwanie, od 0,30 USD/1K wyszukiwań, a ponowienia nieudanych wywołań są bezpłatne. Płatność kryptowalutą, bez KYC. Poniższy kod wymaga tylko `requests` lub `httpx`.

## Konfiguracja Pythona w skrócie

| Atrybut | Wartość |
| --- | --- |
| Instalacja | `pip install requests` lub `pip install httpx` |
| Klucz | Zmienna środowiskowa `SERPCRYPTO_API_KEY` |
| Nagłówek | `Authorization: Bearer <key>` |
| Limit czasu | 60 do 90 sekund: wyszukiwanie odbywa się na żywo |
| Ponawianie | Tylko 429, 502 i 504, z wykładniczym opóźnieniem; błędy są bezpłatne |
| Równoległe wyszukiwania | Do `concurrency_limit` od `GET /credits` |

## Jak skonfigurować klienta wielokrotnego użytku w Pythonie?

Utwórz jeden `requests.Session` z kluczem w nagłówkach i polityką ponawiania dla trzech błędów tymczasowych. Sesja ponownie wykorzystuje połączenia, więc pętla wyszukiwań zużywa mniej czasu na uzgadnianie TLS. Zapisz plik jako `serp_client.py`; kolejne przykłady go importują.

`Retry` z urllib3 czeka dłużej przed każdą nową próbą i respektuje nagłówek `Retry-After`, jeśli zostanie wysłany. Nigdy nie ponawia `400`, `401` ani `402`, które wymagają poprawki, a nie drugiej próby.

*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())
```

## Jak zebrać więcej niż 10 wyników?

Poproś o kolejne strony jedna po drugiej. Około 10 wyników organicznych na stronę, tak jak Google serwuje od czasu, gdy we wrześniu 2025 przestało respektować num=100; każda dodatkowa strona to jeden kredyt więcej. Zatrzymaj się, gdy tylko brakuje `pagination.next_page`: nie ma już czego pobierać, a kredyty zachowujesz.

W większości prac związanych ze śledzeniem pozycji wystarczy pierwsza strona lub pierwsze trzy strony, bo tam koncentrują się kliknięcia. Trzydzieści wyników dla jednego słowa kluczowego kosztuje trzy kredyty.

*Paginacja: do trzech stron, wczesne zatrzymanie*

```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")
```

## Jak uruchomić wiele wyszukiwań równolegle?

Użyj `httpx.AsyncClient` z `asyncio.Semaphore` dopasowanym do limitu Twojego konta. Skrypt odczytuje `concurrency_limit` z endpointu bezpłatnych kredytów, więc dostosowuje się, gdy support podniesie Twój limit. Wyszukiwania powyżej limitu i tak dostałyby `429`; semafor pozwala uniknąć marnowania tych prób.

Każde zadanie ponawia błędy tymczasowe z rosnącą pauzą i zwraca `None` po czterech niepowodzeniach, więc jedno uparte zapytanie nigdy nie blokuje całej partii.

*asyncio + httpx: równoległe wyszukiwania w ramach limitu*

```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"]))
```

## Jak zapisać dzienne pozycje do pliku CSV?

Dodaj jeden wiersz na wynik, z dniem, słowem kluczowym, pozycją, linkiem i ustawieniami zastosowanymi przez API. Odczyt `gl` i `device` z `search_parameters`, a nie z własnych zmiennych, sprawia, że plik zapisuje to, co faktycznie zostało użyte.

Uruchamiaj skrypt raz dziennie przez cron lub Windows Task Scheduler. Trzy słowa kluczowe na mobile kosztują trzy kredyty dziennie, około 90 miesięcznie.

*Dopisz dzisiejsze pozycje do 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"],
            })
```

## Którego klienta HTTP w Pythonie powinienem użyć?

Użyj `requests` do skryptów i zadań cron: jest prosty, a jego adapter ponawiania jest dojrzały. Użyj `httpx`, gdy potrzebujesz kodu asynchronicznego, np. aplikacji webowej, agenta lub partii setek słów kluczowych. Oba wysyłają to samo zapytanie i otrzymują ten sam JSON; API nie dba o to, który wybierzesz.

Unikaj bardzo krótkich limitów czasu w obu bibliotekach. Klient, który poddaje się po pięciu sekundach, może ponownie wysłać wyszukiwanie, które wciąż trwało, i zapłacić za oba.

## Ile będzie kosztował mój skrypt?

Licz wyszukiwania, nie wyniki: jedno wywołanie to jeden kredyt, gdy się powiedzie. Zadanie 500 słów kluczowych, po jednej stronie każdego, codziennie przez 30 dni, to 15 000 wyszukiwań. Na pakiecie 25 000 wyszukiwań (18,75 USD) zostaje zapas, a Prepaid kredyty wyszukiwania nigdy nie wygasają: niewykorzystane wyszukiwania pozostają na Twoim koncie, dopóki ich nie wykorzystasz.

Sprawdź saldo z kodu za pomocą helpera `credits()` powyżej; nic to nie kosztuje.

## Pytania o Python

### Czy jest pakiet SerpCrypto na PyPI?

Nie. Przykłady wywołują endpoint HTTPS za pomocą `requests` lub `httpx`, dwóch powszechnie używanych bibliotek, więc nie ma niczego naszego do zainstalowania ani aktualizacji. Powyższy klient ma około 40 linii i należy do Ciebie.

### Które wersje Pythona obsługuje ten kod?

Python 3.9 i nowsze. Przykład asynchroniczny używa `asyncio.run`, dostępnego od Pythona 3.7, a reszta korzysta tylko z biblioteki standardowej plus `requests` lub `httpx`.

### Czy mogę używać API z notebooka Jupyter?

Tak. Ustaw `SERPCRYPTO_API_KEY` przed uruchomieniem Jupyter lub odczytaj klucz za pomocą `getpass` w notebooku, żeby nie trafił do zapisanej komórki. W notebooku użyj `await main(...)` zamiast `asyncio.run(main(...))`.

### Jak zamienić wyniki w pandas DataFrame?

Przekaż listę słowników wyników do `pandas.DataFrame(data["organic_results"])`. Każde pole staje się kolumną; brakujące pola opcjonalne, takie jak `date`, stają się pustymi komórkami.

---

SerpCrypto: SerpCrypto to API SERP dla deweloperów i agentów AI, które zwraca wyniki wyszukiwania Google i Bing w formacie JSON, z płatnością kryptowalutą i bez przesyłania dokumentów tożsamości. Przedpłacone kredyty wyszukiwania od 0,30 USD/1K wyszukiwań nigdy nie wygasają. Bez KYC — bez dokumentu, bez selfie, bez dokumentów. Płatność kryptowalutą.
