Cómo Google detecta Scrapers SERP
Google invierte fuertemente en proteger sus resultados de búsqueda de acceso automatizado. Antes de que pueda evitar bloques, necesita entender los métodos de detección que Google emplea. Cada método apunta una señal diferente, y la eliminación eficaz de SERP requiere abordar todos ellos simultáneamente.
Para una descripción completa de la arquitectura de raspado SERP con proxies, vea nuestra SERP raspado con guía de proxies.
Detección basada en IP
La primera línea de defensa es el análisis IP. Google rastrea el volumen de consulta por dirección IP y marca aquellos que exceden los patrones normales de búsqueda humana. Las señales específicas incluyen:
- Frecuencia de solicitud: Más de unas cuantas búsquedas por minuto de una sola tasa de activación IP limita
- reputación IP: Los rangos IP de centro de datos conocidos reciben escrutinio inmediato
- Inconsistencia geográfica: Un IP de Alemania que hace consultas dirigidas por Estados Unidos en inglés levanta banderas
- Análisis ASN: Google identifica bloques IP pertenecientes a proveedores de alojamiento vs ISPs
Marcado del navegador
Más allá de las direcciones IP, Google examina la solicitud en sí mismo para señales de automatización:
| Signal | Lo que Google chequea | Bandera roja |
|---|---|---|
| User-Agent | Navegador y cadena de identificación OS | Desaparecido, obsoleto o inconsistente con otros encabezados |
| Aceptar encabezados | Preferencias del tipo de contenido | Falta de valores aceptables o no estándar |
| TLS huella dactilar | Características del apretón de manos SSL/TLS | Fingerprint coincide con las conocidas bibliotecas HTTP (requestas, urllib) |
| Ejecución de JavaScript | Comportamiento de script lado cliente | No Ejecución de JavaScript (detección sin cabeza) |
| Comportamiento de cookies | Aceptación y gestión de cookies | Solicitudes sin cookies ni patrones idénticos de cookies |
Para una mirada más profunda a estas técnicas, lea nuestro artículo sobre cómo los sistemas antibot detectan proxies.
Análisis conductual
Google analiza patrones a través de solicitudes para detectar automatización:
- Solicitud de tiempo: Los intervalos perfectamente consistentes entre solicitudes (por ejemplo, exactamente 3 segundos separados) son antinaturales
- Patrones de consulta: Alfabéticamente o en secuencias predecibles parece automatizada
- Comportamiento de sesión: Los usuarios reales navegan por múltiples páginas, hacen clic en los resultados y pasan tiempo leyendo — los raspadores sólo buscan SERPs
- Patrones de volumen: Los picos súbitos en volumen de consulta de IPs relacionadas sugieren raspado coordinado
The Three Layers of Anti-Block Strategy
Evitar bloques de Google requiere un enfoque de capa. Ninguna técnica es suficiente por sí sola.
Capa 1: Infraestructura proxy
Su elección proxy es la base de su estrategia antibloqueo. ProxyHat proxies residenciales proporcionar la diversidad de IP y el nivel de confianza necesario para el raspado de SERP sostenido.
Capa 2: Solicitar configuración
Cada solicitud HTTP debe parecer que viene de un navegador real. Los encabezados, las cookies y el tiempo deben ser realistas.
Capa 3: Patrones conductuales
El patrón general de su actividad de raspado debe imitar el comportamiento de búsqueda natural. Esto significa retrasos aleatorizados, secuencias de consulta variadas y volúmenes de solicitud adecuados.
Proxies Residenciales: Su Primera Defensa
El cambio único más impactante que puedes hacer es cambiar de centro de datos a proxies residenciales. Aquí es por qué los IPs residenciales son fundamentalmente diferentes desde la perspectiva de Google:
- Los IPs residentes pertenecen a ISPs reales (Comcast, AT plagaT, BT, Deutsche Telekom), no proveedores de nube
- Google no puede bloquear rangos IP residenciales sin bloquear usuarios legítimos
- Cada IP tiene un historial de navegación y una reputación construida por su verdadero usuario
- IPs residenciales apoyan geo-targeting a nivel de ciudad para SERPs exactos
Configuración Proxy para Scraping SERP
import requests
# ProxyHat residential proxy with automatic rotation
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
session = requests.Session()
session.proxies = {
"http": PROXY_URL,
"https": PROXY_URL,
}
# Each request automatically gets a new residential IP
response = session.get(
"https://www.google.com/search",
params={"q": "best proxy service", "num": 10, "hl": "en", "gl": "us"},
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"DNT": "1",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
},
timeout=15,
)Referirse al Documentación de ProxyHat para la rotación avanzada y la configuración de sesión.
Realistic Request Headers
Los encabezados incompletos o inconsistentes son una de las razones más comunes que los raspadores se bloquean. Aquí está un conjunto completo de cabecera realista:
import random
# Rotate between realistic User-Agent strings
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3 Safari/605.1.15",
]
def get_headers():
ua = random.choice(USER_AGENTS)
headers = {
"User-Agent": ua,
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"DNT": "1",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Cache-Control": "max-age=0",
}
# Firefox has different Sec-Ch headers
if "Firefox" not in ua:
headers["Sec-Ch-Ua"] = '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"'
headers["Sec-Ch-Ua-Mobile"] = "?0"
headers["Sec-Ch-Ua-Platform"] = '"Windows"' if "Windows" in ua else '"macOS"'
return headersMantenga siempre actualizadas sus cadenas User-Agent con las versiones actuales del navegador. Enviar un Chrome 90 User-Agent en 2026 es una bandera roja inmediata.
Tasa de limitación y solicitud
El patrón de sus solicitudes importa tanto como las propias solicitudes. Aquí están probados las estrategias de tiempo:
Retrasos aleatorios
Nunca utilice intervalos fijos entre solicitudes. En lugar de ello, aleatorice los retrasos al comportamiento de búsqueda humana imitadora:
import time
import random
def human_delay():
"""Generate a realistic delay between searches."""
# Base delay: 3-8 seconds (normal browsing pace)
base = random.uniform(3, 8)
# Occasionally add longer pauses (simulating reading results)
if random.random() < 0.15:
base += random.uniform(10, 30)
# Rare very short delays (rapid refinement searches)
if random.random() < 0.05:
base = random.uniform(1, 2)
return base
# Usage in scraping loop
for keyword in keywords:
result = scrape_serp(keyword)
delay = human_delay()
time.sleep(delay)Solicitud de guías de volumen
| Tipo Proxy | Solicitudes seguras/Min por IP | Max Concurrent IPs |
|---|---|---|
| Residencial (rota) | 1-2 | Unlimited (pool rota) |
| Residencial (período de sesiones) | 1 por 30 | Basado en tamaño de la piscina |
| Datacenter | 1 por 60 | Limitado por cuenta IP |
Manejo de CAPTCHAs y bloques
Incluso con las mejores precauciones, ocasionalmente encontrará bloques. Construye tu raspador para manejarlos con gracia.
Detectar bloques
def is_blocked(response):
"""Check if Google has blocked or challenged the request."""
# HTTP 429: Rate limited
if response.status_code == 429:
return "rate_limited"
# HTTP 503: Service unavailable (temporary block)
if response.status_code == 503:
return "service_unavailable"
text = response.text.lower()
# CAPTCHA detection
if "captcha" in text or "recaptcha" in text:
return "captcha"
# Unusual traffic message
if "unusual traffic" in text or "automated queries" in text:
return "unusual_traffic"
# Empty or suspicious results
if "did not match any documents" in text and len(text) < 5000:
return "empty_suspicious"
return NoneEstrategia de entrada
import time
import random
def scrape_with_retry(keyword, max_retries=3):
"""Scrape a SERP with automatic retry on blocks."""
for attempt in range(max_retries):
proxy_url = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
proxies = {"http": proxy_url, "https": proxy_url}
response = requests.get(
"https://www.google.com/search",
params={"q": keyword, "num": 10, "hl": "en", "gl": "us"},
headers=get_headers(),
proxies=proxies,
timeout=15,
)
block_type = is_blocked(response)
if block_type is None:
return parse_results(response.text)
if block_type == "rate_limited":
# Exponential backoff
wait = (2 ** attempt) * 5 + random.uniform(0, 5)
print(f"Rate limited. Waiting {wait:.1f}s (attempt {attempt + 1})")
time.sleep(wait)
elif block_type == "captcha":
# Switch to a new IP and wait
print(f"CAPTCHA detected. Rotating IP and waiting...")
time.sleep(random.uniform(10, 20))
else:
# Generic block: wait and retry
time.sleep(random.uniform(5, 15))
return None # All retries exhaustedConsistencia geográfica
Una medida sutil pero importante contra la detección es asegurar la coherencia geográfica a través de sus parámetros de solicitud:
- Si su IP proxy está en los Estados Unidos, establece
gl=usyhl=en - Coincide con el encabezado Aceptar-Lenguaje al lugar de destino
- Utilice una cadena de usuario-agente para una combinación OS/browser común en ese país
- Establecer tiempos de solicitud apropiados para la zona horaria
ProxyHat geo-targeting feature permite seleccionar proxies de países y ciudades específicos, por lo que es sencillo mantener esta consistencia. Más información sobre el uso de solicitudes orientadas a la ubicación en nuestra guía raspando sin ser bloqueado.
Node.js Aplicación antibloqueo
Aquí está la estrategia equivalente antibloqueo implementada en Node.js:
const axios = require('axios');
const cheerio = require('cheerio');
const { HttpsProxyAgent } = require('https-proxy-agent');
const USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0',
];
function getRandomUA() {
return USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)];
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function scrapeWithRetry(keyword, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@gate.proxyhat.com:8080');
try {
const { data, status } = await axios.get('https://www.google.com/search', {
params: { q: keyword, num: 10, hl: 'en', gl: 'us' },
headers: {
'User-Agent': getRandomUA(),
'Accept': 'text/html,application/xhtml+xml',
'Accept-Language': 'en-US,en;q=0.9',
},
httpsAgent: agent,
timeout: 15000,
validateStatus: () => true,
});
if (status === 429) {
const wait = Math.pow(2, attempt) * 5000 + Math.random() * 5000;
console.log(`Rate limited. Waiting ${(wait/1000).toFixed(1)}s`);
await sleep(wait);
continue;
}
if (data.toLowerCase().includes('captcha')) {
console.log('CAPTCHA detected. Rotating IP...');
await sleep(10000 + Math.random() * 10000);
continue;
}
return cheerio.load(data);
} catch (err) {
console.log(`Attempt ${attempt + 1} failed: ${err.message}`);
await sleep(5000 + Math.random() * 10000);
}
}
return null;
}Técnicas avanzadas
Aleatoria de consultas
No raspe las palabras clave en orden alfabético o secuencial. Saque su lista de palabras clave antes de cada carrera:
import random
keywords = ["proxy service", "web scraping", "serp tracking", "seo tools"]
random.shuffle(keywords)
# Now scrape in random order
for kw in keywords:
scrape_with_retry(kw)Parámetros de búsqueda de Google
Utilice estos parámetros para obtener resultados limpios y no personalizados:
| Parámetro | Valor | Propósito |
|---|---|---|
pws | 0 | Desactivar los resultados personalizados |
gl | Código del país | Establecer país de búsqueda |
hl | Código de idioma | Establecer lenguaje de interfaz |
num | 10-100 | Resultados por página |
filter | 0 | Filtro duplicado deshabilitado |
nfpr | 1 | Desactivar la autocorrección |
Programación distribuida
Para el monitoreo de SERP a gran escala, distribuya solicitudes a través del tiempo para evitar patrones de explosión. En lugar de raspar 10.000 palabras clave en una hora, las extendió a través de 8-12 horas con curvas de tráfico natural (más peticiones durante horas de trabajo, menos por noche).
El objetivo no es sólo evitar bloques — es hacer que su tráfico de chatarra indistinguible del comportamiento normal de búsqueda de usuarios. Cada detalle importa.
Para obtener más información sobre la construcción de tuberías de raspado fiables a gran escala, vea nuestra guía completa de proxies de raspado web y Soluciones de raspado web ProxyHat.






