Sans KYC — pas de pièce d'identité, pas de selfie, pas de documents. Payer en crypto : BTC, USDT, USDC, ETH, SOL, LTC
Langue: Français
Obtenir une clé API

Docs · Node.js 18+ · fetch · ESM

API SERP en Node.js : fetch, un pool de workers et pagination

Aucune dépendance : Node.js dispose de fetch depuis la version 18. Un petit client avec des types JSDoc pour les éditeurs et TypeScript, un pool qui respecte la limite de votre compte, et une boucle de pagination qui s'arrête quand les résultats sont épuisés.

Dernière mise à jour: · 5 min de lecture

Réponse rapide

Comment utiliser une API SERP en Node.js ?

Appelez fetch("https://serpcrypto.com/api/v1/search?" + new URLSearchParams({ q })) avec le header Authorization: Bearer <key> et lisez await res.json(). Node.js 18+ ne nécessite aucun package. SerpCrypto renvoie les résultats Google ou Bing en JSON pour 1 crédit par recherche réussie, à partir de 0,30 $US/1K requêtes, et ne facture jamais les erreurs. Paiement en crypto, sans KYC.

Configuration Node.js en un coup d'œil

RuntimeNode.js 18 ou supérieur (fetch, AbortSignal.timeout intégrés)
ModulesModules ES : fichiers .mjs ou "type": "module" dans package.json
Cléprocess.env.SERPCRYPTO_API_KEY
Délai d'expiration90 secondes avec AbortSignal.timeout(90_000)
Recherches en parallèleUn pool dimensionné sur concurrency_limit
TypesTypedefs JSDoc, lus par VS Code et tsc --checkJs

Comment écrire un petit client typé ?

Regroupez l'endpoint, le header et la gestion des erreurs dans un seul module. Les lignes JSDoc @typedef décrivent la réponse, si bien que les éditeurs complètent automatiquement organic_results et vérifient le typage de votre code sans étape de build. Les utilisateurs de TypeScript peuvent recopier les mêmes formes dans une interface.

La fonction search lève une Error avec le statut HTTP et le code d'erreur de l'API dans son message. Votre code peut ensuite décider de réessayer sur 429, 502 et 504 et de s'arrêter sur les autres, comme l'explique la page des erreurs].

serp-client.mjs
// 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();
}

Comment lancer des recherches en parallèle sans déclencher de 429 ?

Lancez autant de workers que votre compte l'autorise et laissez chacun prendre le mot-clé suivant dans une liste partagée. Le pool lit concurrency_limit depuis l'endpoint des crédits gratuits, il n'envoie donc jamais plus de recherches simultanées que ce que le compte accepte.

Un mot-clé en échec est enregistré et le worker passe au suivant. Relancez les échecs ensuite : les erreurs ne coûtent rien, une seconde passe est donc gratuite jusqu'à la réussite.

batch.mjs : un pool de workers
// 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));

Comment récupérer plusieurs pages de résultats ?

Bouclez sur page et arrêtez-vous dès que pagination.next_page est absent. Environ 10 résultats organiques par page, comme Google les sert depuis qu'il n'honore plus num=100 en septembre 2025 ; chaque page supplémentaire coûte un crédit de plus. Une vérification sur trois pages pour un mot-clé coûte trois crédits ; un mot-clé qui n'a qu'une seule page de résultats coûte un crédit.

pages.mjs
// 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" }));

Puis-je appeler l'API depuis un navigateur ou une edge function ?

Depuis un serveur ou une edge function, oui : Cloudflare Workers, Vercel et Deno fournissent tous le même fetch. Depuis une page de navigateur, non : la clé serait visible par tous les visiteurs. Placez entre les deux une petite route serveur qui détient la clé et ne transmet que les paramètres que vous autorisez.

La même règle s'applique aux applications mobiles. Tout ce qui est livré sur l'appareil d'un utilisateur peut être lu, donc les clés restent sur vos serveurs.

Comment garder des coûts prévisibles en Node.js ?

Comptez les appels que vous faites : un appel réussi correspond à un crédit, à 0,56 $US/1K requêtes sur le pack 100 000 recherches. Vérifiez credits_remaining avant un gros batch et arrêtez le pool quand il approche de zéro plutôt que de récolter une série de réponses 402. Les crédits de recherche prépayés n'expirent jamais : les requêtes inutilisées restent sur votre compte jusqu'à ce que vous les utilisiez, le reste inutilisé est donc conservé pour la tâche suivante.

Questions Node.js

Existe-t-il un package npm pour SerpCrypto ?

Non. Le client ci-dessus fait environ 40 lignes de JavaScript standard qui utilisent fetch, il n'y a donc rien de notre part à installer. Copiez-le dans votre projet et adaptez-le.

Cela fonctionne-t-il avec CommonJS (require) ?

Les exemples utilisent les modules ES pour le await de premier niveau. Dans un fichier CommonJS, enveloppez les appels dans une fonction async et utilisez fetch de la même façon ; c'est global dans Node.js 18+.

Comment l'utiliser avec TypeScript ?

Recopiez les formes JSDoc dans un interface SearchResponse et typez le résultat de res.json() avec. Les blocs optionnels comme organic_results? doivent rester optionnels, car une page peut ne pas les afficher.

Quelle version de Node.js me faut-il ?

Node.js 18 ou ultérieur pour le fetch intégré. AbortSignal.timeout est disponible depuis Node.js 17.3, donc la 18 couvre tout ce qui figure sur cette page.

À partir de 0,30 $US/1K requêtes · sans KYC

Obtenir une clé API