# SERP-API in Node.js: fetch, ein Worker-Pool und Pagination

> SerpCrypto SERP-API in Node.js 18+ mit fetch: ein typisierter Client, ein Worker-Pool unter Ihrem Limit und eine Pagination-Schleife.

- URL: https://serpcrypto.com/de/docs/node/
- Zuletzt aktualisiert: 2026-10-22
- Herausgeber: SerpCrypto (https://serpcrypto.com)

Keine Abhängigkeit: Node.js hat `fetch` seit Version 18. Ein kleiner Client mit JSDoc-Typen für Editoren und TypeScript, ein Pool, der das Limit Ihres Kontos einhält, und eine Pagination-Schleife, die stoppt, wenn die Ergebnisse ausgehen.

**Kurze Antwort — Wie verwende ich eine SERP-API in Node.js?**

Rufen Sie `fetch("https://serpcrypto.com/api/v1/search?" + new URLSearchParams({ q }))` mit dem Header `Authorization: Bearer <key>` auf und lesen Sie `await res.json()`. Node.js 18+ braucht kein Paket. **SerpCrypto** liefert Google- oder Bing-Ergebnisse als JSON für 1 Credit pro erfolgreicher Suche, ab 0,30 $/1K Suchanfragen, und berechnet Fehler nie. Mit Krypto bezahlen, ohne KYC.

## Node.js-Setup auf einen Blick

| Attribut | Wert |
| --- | --- |
| Laufzeitumgebung | Node.js 18 oder neuer (integriertes `fetch`, `AbortSignal.timeout`) |
| Module | ES-Module: `.mjs`-Dateien oder `"type": "module"` in package.json |
| Schlüssel | `process.env.SERPCRYPTO_API_KEY` |
| Timeout | 90 Sekunden mit `AbortSignal.timeout(90_000)` |
| Parallele Suchen | Ein Pool dimensioniert auf `concurrency_limit` |
| Typen | JSDoc-Typedefs, gelesen von VS Code und `tsc --checkJs` |

## Wie schreibe ich einen kleinen typisierten Client?

Legen Sie den Endpoint, den Header und die Fehlerbehandlung in ein Modul. Die JSDoc-Zeilen `@typedef` beschreiben die Antwort, sodass Editoren `organic_results` vervollständigen und Ihren Code ohne Build-Schritt typisieren.

Die Funktion `search` wirft einen `Error` mit dem HTTP-Status und dem Fehler-`code` der API in der Meldung. Ihr Code kann dann entscheiden, bei `429`, `502` und `504` erneut zu versuchen und bei den anderen abzubrechen, wie es die [Fehlerseite](https://serpcrypto.com/de/docs/errors/) erklärt.

*serp-client.mjs*

```javascript
// serp-client.mjs — Node.js 18+, no dependency
const API_URL = "https://serpcrypto.com/api/v1/search";
const CREDITS_URL = "https://serpcrypto.com/api/v1/credits";
const headers = { Authorization: `Bearer ${process.env.SERPCRYPTO_API_KEY}` };

/**
 * @typedef {Object} OrganicResult
 * @property {number} position
 * @property {string} title
 * @property {string} link
 * @property {string} [snippet]
 * @property {string} [date]
 */

/**
 * @typedef {Object} SearchResponse
 * @property {Object} search_metadata
 * @property {string} search_metadata.id
 * @property {string} search_metadata.status
 * @property {number} search_metadata.credits_used
 * @property {OrganicResult[]} [organic_results]
 * @property {Object} [pagination]
 * @property {number} pagination.current
 * @property {number} [pagination.next_page]
 */

/**
 * Run one search (1 credit when it succeeds).
 * @param {string} q
 * @param {Record<string, string | number>} [params]
 * @returns {Promise<SearchResponse>}
 */
export async function search(q, params = {}) {
  const query = new URLSearchParams({ q, ...Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])) });
  const res = await fetch(`${API_URL}?${query}`, { headers, signal: AbortSignal.timeout(90_000) });
  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    const err = new Error(`${res.status} ${body.error?.code ?? "error"}: ${body.error?.message ?? ""}`);
    err.status = res.status;
    throw err;
  }
  return res.json();
}

/** Free: credits left, used today and the concurrency limit. */
export async function credits() {
  const res = await fetch(CREDITS_URL, { headers });
  if (!res.ok) throw new Error(`credits: HTTP ${res.status}`);
  return res.json();
}
```

## Wie führe ich Suchen parallel aus, ohne auf 429 zu stoßen?

Starten Sie so viele Worker, wie Ihr Account erlaubt, und lassen Sie jeden den nächsten Suchbegriff aus einer gemeinsamen Liste nehmen. Der Pool liest `concurrency_limit` aus dem Endpoint für Gratis-Credits, sodass er nie mehr Suchen gleichzeitig sendet, als der Account akzeptiert.

Ein fehlgeschlagener Suchbegriff wird vermerkt, und der Worker macht weiter. Starten Sie die Fehlschläge danach erneut: Fehler kosten nichts, ein zweiter Durchlauf ist also gratis, bis er erfolgreich ist.

*batch.mjs: ein Pool aus Workern*

```javascript
// batch.mjs — parallel searches, never more than the account's limit at once
import { search, credits } from "./serp-client.mjs";

const keywords = ["password manager", "note taking app", "time tracking software", "invoice software"];
const { concurrency_limit: limit } = await credits();

let next = 0;
const results = new Map();

async function worker() {
  while (next < keywords.length) {
    const kw = keywords[next++];
    try {
      const data = await search(kw, { gl: "us", hl: "en" });
      results.set(kw, data.organic_results?.[0]?.link ?? null);
    } catch (err) {
      results.set(kw, `failed: ${err.message}`);
    }
  }
}

await Promise.all(Array.from({ length: Math.min(limit, keywords.length) }, worker));
console.table(Object.fromEntries(results));
```

## Wie rufe ich mehrere Ergebnisseiten ab?

Schleifen Sie über `page` und stoppen Sie, sobald `pagination.next_page` fehlt. Etwa 10 organische Ergebnisse pro Seite, so wie Google sie liefert, seit num=100 im September 2025 nicht mehr berücksichtigt wird; jede weitere Seite kostet einen weiteren Credit. Eine Prüfung über drei Seiten für einen Suchbegriff kostet drei Credits; ein Suchbegriff mit nur einer Ergebnisseite kostet eine.

*pages.mjs*

```javascript
// pages.mjs — up to three pages, stop when results end
import { search } from "./serp-client.mjs";

async function topResults(q, pages = 3, params = {}) {
  const rows = [];
  for (let page = 1; page <= pages; page++) {
    const data = await search(q, { ...params, page });
    for (const r of data.organic_results ?? []) rows.push({ page, position: r.position, link: r.link });
    if (!data.pagination?.next_page) break; // nothing more: save the credits
  }
  return rows;
}

console.log(await topResults("headless cms", 3, { gl: "de", hl: "en" }));
```

## Kann ich die API aus einem Browser oder einer Edge-Funktion aufrufen?

Aus einem Server oder einer Edge-Funktion ja: Cloudflare Workers, Vercel und Deno bieten alle das gleiche `fetch`. Aus einer Browserseite nein: Der Schlüssel wäre für jeden Besucher sichtbar. Schalten Sie eine kleine Server-Route dazwischen, die den Schlüssel hält und nur die Parameter weiterleitet, die Sie erlauben.

Dieselbe Regel gilt für mobile Apps. Alles, was auf das Gerät eines Nutzers ausgeliefert wird, kann gelesen werden, daher bleiben Schlüssel auf Ihren Servern.

## Wie halte ich die Kosten in Node.js planbar?

Zählen Sie Ihre Aufrufe: Ein erfolgreicher Aufruf ist ein Credit, zu 0,56 $/1K Suchanfragen im 100.000 Suchanfragen-Paket. Prüfen Sie `credits_remaining` vor einem großen Batch und stoppen Sie den Pool, wenn er sich der Null nähert, statt eine Reihe von `402`-Antworten zu sammeln. Vorausbezahlte Such-Credits verfallen nie: ungenutzte Suchen bleiben auf Ihrem Konto, bis Sie sie verwenden, sodass ein ungenutzter Rest für den nächsten Job erhalten bleibt.

## Node.js-Fragen

### Gibt es ein npm-Paket für SerpCrypto?

Nein. Der Client oben umfasst etwa 40 Zeilen Standard-JavaScript mit `fetch`, es gibt also nichts von uns zu installieren. Kopieren Sie ihn in Ihr Projekt und passen Sie ihn an.

### Funktioniert das mit CommonJS (require)?

Die Beispiele verwenden ES-Module für `await` auf oberster Ebene. In einer CommonJS-Datei wickeln Sie die Aufrufe in eine `async`-Funktion und verwenden `fetch` genauso; es ist ab Node.js 18+ global.

### Wie verwende ich es mit TypeScript?

Kopieren Sie die JSDoc-Formen in ein `interface SearchResponse` und typisieren Sie damit das Ergebnis von `res.json()`. Optionale Blöcke wie `organic_results?` müssen optional bleiben, da eine Seite sie möglicherweise nicht zeigt.

### Welche Node.js-Version brauche ich?

Node.js 18 oder höher für das integrierte `fetch`. `AbortSignal.timeout` ist ab Node.js 17.3 verfügbar, 18 deckt also alles auf dieser Seite ab.

---

SerpCrypto: SerpCrypto ist eine SERP-API für Entwickler und KI-Agenten, die Google- und Bing-Ergebnisse als JSON zurückgibt und mit Krypto bezahlt wird, ohne Ausweisupload. Vorausbezahlte Such-Credits ab 0,30 $/1K Suchanfragen verfallen nie. Ohne KYC — kein Ausweis, kein Selfie, keine Dokumente. Mit Krypto bezahlen.
