Respuesta rápida
¿Qué errores de la API SERP conviene reintentar y se cobran las búsquedas fallidas?
SerpCrypto nunca cobra un error: solo una búsqueda exitosa usa 1 crédito. Reintenta 429 concurrency_limit, 502 search_failed y 504 search_timeout con retroceso exponencial. No reintentes 400, 401 ni 402: corrige antes el parámetro, la clave o el saldo. Los créditos cuestan desde 0,30 US$/1K búsquedas y nunca caducan; el pago es con criptomonedas, sin KYC.
¿Qué significa cada código de error?
Ninguna fila de esta tabla consume un crédito. 1 crédito = 1 consulta correcta, que devuelve una página de resultados en cualquier motor compatible. Una consulta fallida no se cobra.
| HTTP | code | Causa | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|
| 400 | invalid_parameter | Falta q o un valor está fuera de la lista permitida | Corrige la solicitud; el mensaje indica el parámetro | No |
| 401 | invalid_api_key | No hay clave, la clave está mal escrita o revocada | Revisa el header o api_key; crea una nueva clave si es necesario | No |
| 402 | insufficient_credits | La cuenta tiene 0 créditos | Compra un pack con tu saldo | Después de comprar |
| 429 | concurrency_limit | Más búsquedas a la vez de las que permite tu cuenta | Espera, reduce el paralelismo o pide a soporte un límite mayor | Sí, con backoff |
| 502 | search_failed | El engine o la colección falló para esta solicitud | Reintenta la misma solicitud | Sí, con backoff |
| 504 | search_timeout | Sin respuesta a tiempo | Reintenta la misma solicitud | Sí, con backoff |
¿Cómo es una respuesta de error?
Todos los errores tienen el mismo body JSON pequeño, con un code estable y un message legible para personas. Bifurca según code en tu programa y registra message para las personas. El status HTTP coincide con la tabla anterior.
{
"error": {
"code": "insufficient_credits",
"message": "Your account has no search credits left."
}
}¿Por qué recibo 400 invalid_parameter?
Falta un valor obligatorio o un valor está fuera de la lista que acepta la API. Las causas habituales son un q vacío, un nombre de engine con una errata como google-news en lugar de google_news, un page mayor que 10, o un device distinto de desktop o mobile.
El message indica el parámetro culpable. Compara tu solicitud con la referencia de la API; no se cobra nada, así que puedes corregir y reenviar al momento.
¿Por qué recibo 401 invalid_api_key?
La clave no llegó a la API o no es válida. Comprueba que el header sea exactamente Authorization: Bearer YOUR_KEY, con un espacio después de Bearer. Comprueba también que tu variable de entorno esté definida en el shell o servicio que ejecuta el código, no solo en tu terminal. Una clave revocada seguirá fallando: crea una nueva en el dashboard.
¿Qué hago con 402 insufficient_credits?
Compra un pack de créditos con tu saldo y vuelve a enviar. Si el saldo es demasiado bajo, recarga primero con criptomonedas; la recarga mínima es 25 US$. Lee credits_remaining de GET https://serpcrypto.com/api/v1/credits antes de un trabajo grande para no detenerte a mitad: esa llamada es gratis.
¿Cómo manejo 429 concurrency_limit?
Baja el ritmo en lugar de parar. El límite cuenta las búsquedas que se ejecutan a la vez, no las búsquedas por día. Cada cuenta puede ejecutar un número determinado de consultas al mismo tiempo; el límite se muestra en tu dashboard y se amplía a petición. Lee concurrency_limit del endpoint de créditos y dimensiona tu pool de workers según ese valor; las páginas de Python y Node.js muestran un pool que nunca lo supera.
¿Cuándo se devuelven 502 y 504?
502 search_failed significa que la búsqueda no se pudo completar para esta solicitud; 504 search_timeout significa que no se completó a tiempo. Ambos son gratis y ambos merecen un reintento. Espera un poco más antes de cada nuevo intento, como hace el código de abajo, y abandona tras cinco intentos para que un trabajo atascado no entre en bucle para siempre.
import os
import random
import time
import requests
API_URL = "https://serpcrypto.com/api/v1/search"
RETRYABLE = {429, 502, 504}
def search(params, max_attempts=5):
headers = {"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]}
for attempt in range(1, max_attempts + 1):
r = requests.get(API_URL, params=params, headers=headers, timeout=90)
if r.status_code == 200:
return r.json()
error = r.json().get("error", {})
if r.status_code not in RETRYABLE or attempt == max_attempts:
raise RuntimeError(f"{r.status_code} {error.get('code')}: {error.get('message')}")
# exponential backoff with jitter: about 1 s, 2 s, 4 s, 8 s
time.sleep(2 ** (attempt - 1) + random.random())
raise RuntimeError("unreachable")
print(search({"q": "solar panel installers", "gl": "au", "hl": "en"})["search_metadata"])// retry.mjs — Node.js 18+
const API_URL = "https://serpcrypto.com/api/v1/search";
const RETRYABLE = new Set([429, 502, 504]);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export async function search(params, maxAttempts = 5) {
const url = `${API_URL}?${new URLSearchParams(params)}`;
const headers = { Authorization: `Bearer ${process.env.SERPCRYPTO_API_KEY}` };
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const res = await fetch(url, { headers });
if (res.ok) return res.json();
const body = await res.json().catch(() => ({}));
const code = body.error?.code ?? "unknown";
if (!RETRYABLE.has(res.status) || attempt === maxAttempts) {
throw new Error(`${res.status} ${code}: ${body.error?.message ?? ""}`);
}
// exponential backoff with jitter: about 1 s, 2 s, 4 s, 8 s
await sleep(1000 * 2 ** (attempt - 1) + Math.random() * 1000);
}
throw new Error("unreachable");
}
console.log((await search({ q: "solar panel installers", gl: "au", hl: "en" })).search_metadata);¿Mi timeout HTTP debe ser corto o largo?
Lo bastante largo para que una búsqueda termine: una búsqueda se ejecuta en vivo, así que configura el timeout de tu cliente en 60 a 90 segundos en lugar de unos pocos segundos. Un cliente que se rinde demasiado pronto envía una segunda solicitud mientras la primera sigue en curso, lo que desperdicia un slot de concurrencia y, si ambas tienen éxito, dos créditos.
Preguntas sobre errores
¿Se cobra una búsqueda si mi programa se cae antes de leer la respuesta?
Sí, si la API completó la búsqueda y devolvió 200: el crédito se usa cuando la búsqueda se completa con éxito, no cuando la lees. Es otra razón para configurar un timeout largo en el cliente.
¿Los reintentos cuestan más?
Solo el intento que sale bien usa un crédito. Los intentos fallidos con 429, 502 o 504 son gratis, así que una solicitud que sale bien al tercer intento cuesta 1 crédito en total.
¿Dónde reporto un error que vuelve a aparecer?
Escribe a [email protected] con el search_metadata.id de una búsqueda exitosa o la hora, el motor y los parámetros de la que falla. Respuestas por email en menos de 12 horas, 7 días a la semana, incluida la ayuda con la integración de la API.