Cómo raspar Google Maps a gran escala con un agente de IA y el servidor MCP de Scrapeless
Advanced Bot Mitigation Engineer
Principales Conclusiones:
- Funciona en cualquier cliente que soporte MCP. El Servidor MCP de Scrapeless expone el navegador en la nube como un conjunto de herramientas del Protocolo de Contexto de Modelo — Claude Desktop, Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI, VS Code + GitHub Copilot Chat, o un cliente personalizado construido contra el SDK de TypeScript MCP, todos los llaman de la misma manera. El protocolo es lo que sostiene la carga, no el cliente. Sin pegamento de SDK, sin gestión de subprocesos CLI.
- Los primitivas del navegador se componen en un scraper de Google Maps. El servidor envía herramientas genéricas del navegador —
browser_create,browser_goto,browser_wait_for,browser_get_html,browser_get_text,browser_click,browser_type,browser_press_key,browser_scroll,browser_scroll_to,browser_screenshot,browser_snapshot,browser_close— y el agente las ensambla en el flujo de búsqueda → desplazamiento → extracción que requiere Google Maps. - Dos modos de transporte. El modo Stdio ejecuta el servidor localmente a través de
npx scrapeless-mcp-servery es la opción predeterminada correcta para clientes MCP de escritorio en una estación de trabajo. El modo HTTP transmitible dirige al cliente ahttps://api.scrapeless.com/mcpy es la opción predeterminada correcta para agentes alojados en la nube. - Renderizado en la nube más proxies residenciales. Google Maps es una SPA pesada en JavaScript que carga resultados de manera diferida como un feed. Scrapeless Scraping Browser maneja el renderizado de JS, egresos por proxy residencial y la huella de detección anti-detección en cada sesión — el agente solo tiene que manejar la página. Las sesiones se asignan a través de la región de proxy para la que está configurada la cuenta de Scrapeless; no hay sobrescritura de región por llamada expuesta a través de la superficie de herramientas MCP hoy.
- Límite de lista de resultados por consulta. Google Maps muestra hasta 120 resultados por consulta en el feed lateral. Más allá de eso, la estrategia es una cuadrícula geográfica: dividir el área de búsqueda en cuadros delimitadores más pequeños, ejecutar una consulta por cuadro y deduplicar por id de lugar.
- Gratis para comenzar. Las nuevas cuentas de Scrapeless incluyen tiempo de ejecución de Scraping Browser gratis — regístrate en Scrapeless.
Introducción: un camino nativo de MCP hacia los datos de Google Maps
Google Maps es uno de los conjuntos de datos públicos de negocios más ricos en la web abierta — nombres, direcciones, calificaciones, conteos de reseñas, horarios, enlaces de fotos, etiquetas de categoría, detalles de contacto y un id de lugar estable para cada entrada. Para equipos de SEO local, pipelines de generación de leads, análisis de bienes raíces y mapeo de ubicación de competidores, ese conjunto de datos es la base del flujo de trabajo.
La página en sí es difícil de manejar sin un navegador real. La vista del mapa carga su propio SDK, el panel lateral pagina cargando de manera diferida a medida que se desplaza el feed, los paneles de detalles de cada lugar se abren a través de clics de usuario y los conteos de resultados alcanzan un máximo de alrededor de 120 por consulta. El scraping puramente HTTP devuelve el shell de JS; los datos viven detrás del DOM renderizado.
Esta publicación explica cómo usar el Servidor MCP de Scrapeless con cualquier cliente que conozca MCP — Claude Desktop, Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI, o un cliente personalizado construido contra el SDK de TypeScript MCP — para raspar Google Maps de principio a fin. El servidor envuelve el Scrapeless Scraping Browser — un navegador en la nube listo para agentes — como un conjunto de herramientas MCP, por lo que el agente llama browser_create / browser_goto / browser_scroll / browser_get_html directamente a través del protocolo en lugar de acceder a una CLI o conectar un SDK. El navegador en la nube maneja el renderizado, los proxies y la capa de anti-detección; el agente gestiona el patrón de descubrimiento → extracción.
Para el mismo objetivo a través de una superficie de integración diferente, consulta la publicación del agente de LangChain o, para la versión CLI de bash, la publicación más amplia de motores de búsqueda.
Lo Que Puedes Hacer Con Esto
- Generación de leads local. Obtén cada dentista, plomero o cafetería en una ciudad objetivo con nombre, dirección, teléfono, sitio web, horarios, calificación y conteo de reseñas.
- Análisis competitivo de SEO local. Realiza un seguimiento del ranking de ubicación de competidores en consultas de palabras clave de categoría y los listados circundantes en el mismo SERP.
- Construcción de conjuntos de datos de bienes raíces y POI. Crea tablas de puntos de interés categorizados — restaurantes por tipo de cocina, cadenas minoristas por región, servicios públicos por código postal — actualizadas en una cadencia continua.
- Seguimiento de reputación. Captura instantáneas de calificación por ubicación, conteo de reseñas y velocidad de reseñas a través de una marca de múltiples ubicaciones para resaltar las ubicaciones fuera de la norma.
- Investigación de mercado. Mapea la densidad y mezcla de categorías de pequeñas empresas en un área objetivo para estimar la saturación del mercado.
- Inteligencia de fotos y precios. Captura capturas de pantalla del panel de ubicación para regresiones visuales, o extrae el indicador de nivel de precios (
$,$$,$$$) por listado.
Por qué Scrapeless Scraping Browser
Scrapeless Scraping Browser es un navegador en la nube personalizable y anti-detección diseñado para rastreadores web y agentes de IA. Para Google Maps específicamente, ofrece:
- Renderización de JavaScript en el lado de la nube para que el SDK del mapa, el feed lateral, la carga perezosa impulsada por el desplazamiento y el panel de detalles del lugar se completen antes de la extracción.
- Proxies residenciales en más de 195 países para que las consultas geográficas devuelvan las listados que un usuario local vería —importante porque los resultados de Google Maps varían según la región de salida.
- Impresion de anti-detección en cada sesión para que la página se renderice de manera idéntica al tráfico orgánico a lo largo de sesiones de desplazamiento prolongadas.
- Persistencia de sesión a través del ID de tarea
browser_create; llamadas posteriores a herramientasbrowser_*en el mismo agente reutilizan el mismo navegador en la nube, manteniendo las cookies, la posición del desplazamiento y el historial de navegación consistentes. - Una única superficie MCP —cada operación que el agente necesita para manejar Maps (
browser_goto,browser_wait_for,browser_scroll,browser_click,browser_get_html,browser_get_text,browser_screenshot) está a un llamado de herramienta de distancia.
Obtén tu clave API en el plan gratuito en Scrapeless. La superficie de herramientas MCP completa está documentada en github.com/scrapeless-ai/scrapeless-mcp-server.
Requisitos previos
- Cualquier cliente que soporte MCP. Claude Desktop (claude.com/download), Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI, VS Code + GitHub Copilot Chat, o un cliente personalizado construido contra el MCP TypeScript SDK —el protocolo es lo que soporta la carga, no el cliente.
- Node.js 18 o superior (para el modo de transporte stdio).
- Una cuenta Scrapeless y clave API —regístrate en Scrapeless.
- Familiaridad básica con la edición del archivo de configuración MCP de tu cliente.
Instalar
El Servidor MCP de Scrapeless está publicado como el paquete npm scrapeless-mcp-server y es llamable desde cualquier cliente que soporte el Protocolo de Contexto de Modelo. El proceso de instalación de cuatro pasos a continuación muestra el camino de instalación para los clientes más comunes (Claude Desktop, Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI), pero el fragmento JSON en sí es portátil: simplemente colócalo en cualquier cliente que tu equipo ya esté utilizando y las mismas llamadas a herramientas funcionarán.
1. Obtén tu clave API de Scrapeless
Regístrate en Scrapeless, abre el panel de control, y desde Configuración → Gestión de Claves API crea una clave. Copia el valor —va en la configuración MCP en el paso 2.
Obtén tu clave API en el plan gratuito al registrarte en Scrapeless y únete a la comunidad oficial:
Comunidad Oficial de Discord de Scrapeless
Comunidad Oficial de Telegram de Scrapeless
2. Agrega el servidor MCP a tu cliente (modo stdio)
La ubicación del archivo de configuración depende del cliente:
Claude Desktop (la aplicación de escritorio de claude.com/download):
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Claude Code (el CLI de terminal):
- Todas las plataformas:
~/.claude.json - O usa el subcomando
claude mcp adden lugar de editar el archivo a mano:bashclaude mcp add scrapeless --scope user --transport stdio \ --env "SCRAPELESS_KEY=YOUR_SCRAPELESS_KEY" \ -- npx -y scrapeless-mcp-server
Cursor: edita ~/.cursor/mcp.json (o usa la Configuración → Interfaz de Usuario MCP de Cursor). Mismo formato JSON que el fragmento a continuación.
OpenAI Codex CLI: Codex lee los servidores MCP desde ~/.codex/config.toml y también expone un asistente codex mcp. El comando de instalación stdio es:
bash
codex mcp add scrapeless \
--env "SCRAPELESS_KEY=YOUR_SCRAPELESS_KEY" \
-- npx -y scrapeless-mcp-server
El equivalente en TOML es:
toml
[mcp_servers.scrapeless]
command = "npx"
args = ["-y", "scrapeless-mcp-server"]
[mcp_servers.scrapeless.env]
SCRAPELESS_KEY = "YOUR_SCRAPELESS_KEY"
Después de editar el archivo, reinicia Codex y confirma la entrada con codex mcp list --json. Codex es estricto con el enmarcado MCP stdio: el proceso del servidor debe escribir solo mensajes JSON-RPC en stdout. Si Codex informa falló el apretón de manos con el servidor MCP, respuesta de inicialización, o conexión cerrada, verifica si el servidor imprimió una línea de registro de inicio en stdout antes de la respuesta JSON-RPC. Actualiza a una versión de servidor corregida o ejecuta el servidor detrás de un pequeño filtro stdio que redirija las líneas stdout no JSON a stderr.
Utiliza el modo stdio como la ruta predeterminada de Codex. Las versiones actuales de Codex CLI exponen codex mcp add --url para servidores HTTP transmitibles, pero la opción de autenticación integrada del helper se basa en tokens portadores, mientras que el punto final MCP alojado de Scrapeless espera el encabezado x-api-token. Utiliza el modo HTTP de Codex solo si tu versión/configuración de Codex admite encabezados HTTP personalizados para servidores MCP.
Gemini CLI: Gemini admite servidores MCP a través de mcpServers en settings.json, además de un helper gemini mcp. El propio Gemini CLI actualmente requiere Node.js 20 o una versión más nueva. Para una instalación de stdio a nivel de usuario, ejecuta:
bash
gemini mcp add -s user \
-e SCRAPELESS_KEY=YOUR_SCRAPELESS_KEY \
scrapeless npx -y scrapeless-mcp-server
O edita ~/.gemini/settings.json directamente:
json
{
"mcpServers": {
"scrapeless": {
"command": "npx",
"args": ["-y", "scrapeless-mcp-server"],
"env": {
"SCRAPELESS_KEY": "YOUR_SCRAPELESS_KEY"
}
}
}
}
Utiliza .gemini/settings.json en su lugar para la configuración específica del proyecto. Confirma con gemini mcp list (o gemini --debug mcp list si tu shell no interactivo no imprime una tabla), o inicia Gemini y ejecuta /mcp para ver el estado de la conexión y las herramientas descubiertas.
VS Code + GitHub Copilot Chat: el mismo fragmento de mcpServers va en la configuración MCP a nivel de espacio de trabajo o de usuario; consulta la documentación de MCP de GitHub Copilot Chat para la ruta activa.
Agrega la entrada del servidor Scrapeless bajo mcpServers:
json
{
"mcpServers": {
"scrapeless": {
"type": "stdio",
"command": "npx",
"args": ["-y", "scrapeless-mcp-server"],
"env": {
"SCRAPELESS_KEY": "YOUR_SCRAPELESS_KEY"
}
}
}
}
Reemplaza YOUR_SCRAPELESS_KEY con la clave del paso 1. Reinicia el cliente para recoger el nuevo servidor. En la primera ejecución, npx -y scrapeless-mcp-server descarga el paquete y comienza el servidor a través de stdio; no se necesita ningún comando de instalación separado. Después del reinicio, el panel MCP del cliente debería listar scrapeless junto a cualquier otro servidor conectado.
3. O usa el modo HTTP transmitible (agentes alojados en la nube)
Para agentes que se ejecutan de forma remota — un servidor Cursor alojado, un runner de CI, un cliente MCP personalizado que se ejecuta en un contenedor — dirige el cliente al punto final MCP alojado de Scrapeless en lugar de ejecutar npx localmente:
json
{
"mcpServers": {
"Scrapeless MCP Server": {
"type": "streamable-http",
"url": "https://api.scrapeless.com/mcp",
"headers": {
"x-api-token": "YOUR_SCRAPELESS_KEY"
},
"disabled": false,
"alwaysAllow": []
}
}
}
La misma YOUR_SCRAPELESS_KEY funciona en ambos modos. El transporte HTTP es el valor predeterminado correcto cuando un binario de stdio no puede ejecutarse junto al agente (sandbox de CI, ejecutores de agentes alojados).
Para Gemini CLI, el helper HTTP y la forma JSON son:
bash
gemini mcp add -s user -t http \
-H "x-api-token: YOUR_SCRAPELESS_KEY" \
scrapeless https://api.scrapeless.com/mcp
json
{
"mcpServers": {
"scrapeless": {
"httpUrl": "https://api.scrapeless.com/mcp",
"headers": {
"x-api-token": "YOUR_SCRAPELESS_KEY"
}
}
}
}
4. Verifica que el servidor MCP esté configurado
Antes del primer raspado real de Maps, prueba la instalación con un prompt:
"Usa el servidor MCP de Scrapeless para abrir https://example.com y dime el título de la página."
El agente debería llamar a browser_create para crear una sesión, luego browser_goto para navegar, luego browser_get_text (o browser_get_html) y responder con "Example Domain". Si eso vuelve, el servidor MCP está cargado, la clave API está configurada y el navegador en la nube es accesible.
Si falla:
| Síntoma | Causa probable | Solución |
|---|---|---|
| "No veo una herramienta de Scrapeless" | El servidor MCP no cargado por el cliente | Vuelve a comprobar la ruta del archivo de configuración, reinicia el cliente, busca el servidor en el indicador MCP del cliente |
Authentication failed / 401 |
Clave API no configurada o vencida | Vuelve a copiar la clave desde el panel, pégala en la configuración, reinicia el cliente |
npx se detiene en la primera ejecución |
Red lenta o tiempo de espera del registro | Ejecución npx -y scrapeless-mcp-server una vez en un terminal para pre-caché el paquete, luego reinicia el cliente |
Codex dice initialize response o connection closed durante el inicio de MCP |
El servidor stdio escribió texto no JSON a stdout antes del apretón de manos JSON-RPC de MCP | Actualiza el servidor o envuélvelo para que solo las líneas JSON-RPC lleguen a stdout y los registros vayan a stderr |
La llamada a la herramienta devuelve Access Denied HTML |
Pool de proxy o desafío anti-bot en una nueva asignación | Pide al agente que intente de nuevo: browser_close y luego browser_create crea una nueva sesión |
Cómo usar esto: prompt a tu agente
Después de la instalación, raspas Google Maps hablando con tu agente — no mediante llamadas manuales a herramientas. El servidor MCP expone el navegador en la nube como una lista de herramientas descubiertas; el agente lee las descripciones de las herramientas y las compone en la secuencia correcta según el prompt.
Prompts que puedes pegar
| Le dices a tu agente | Lo que recibes a cambio |
| "Obtén las 30 mejores cafeterías en Pike Place, Seattle de Google Maps. Devuelve JSON con nombre, calificación, número de reseñas, dirección." | Un registro JSON por lugar con los campos solicitados |
| "Enumera cada dentista en el código postal 90015 con teléfono, sitio web y horarios." | JSON por lugar con información de contacto + horarios |
| "Busca en Google Maps 'restaurantes de sushi cerca del Puente de Brooklyn', desplaza la página hasta el final, devuelve todo." | Hasta ~120 lugares, sin duplicados por nombre + dirección |
| "Para cada resultado, también haz clic en el panel de detalles y extrae la URL del sitio web y la dirección completa." | JSON por lugar enriquecido con campos del panel de detalles |
| "Toma una captura de pantalla de la página de resultados de búsqueda después de desplazarte." | Captura de pantalla + JSON extraído |
| "Encuentra restaurantes italianos en 'San Francisco'. Filtra los que tienen calificación ≥ 4.5 y al menos 200 reseñas." | Lista de lugares filtrada |
| "Ejecuta la misma consulta desde una IP en Madrid — devuelve los resultados de Maps como un usuario español los vería." | Resultados adaptados a la localidad (Rutas sin scraping a través de un proxy residencial en ES) |
| "Para el lugar llamado 'Storyville Coffee Pike Place', abre el panel del lugar y extrae las últimas 10 reseñas." | Carga de reseñas del panel de detalles |
La herramienta browser_create asigna un navegador en la nube fresco y devuelve un id de sesión que el agente utiliza para el resto del flujo. La sesión es la unidad de estado: las cookies, la posición de desplazamiento y el historial de navegación viven dentro de ella.
Llamada a la herramienta (lo que el agente envía a través de MCP):
json
{
"name": "browser_create",
"arguments": {}
}
La herramienta devuelve una carga útil como Nueva sesión de navegador creada con ID: vybp-a64d-2dqf-9vsq86. Las llamadas browser_* subsiguientes en el mismo agente reutilizan automáticamente la sesión activa; pasar el id devuelto como sessionId es compatible pero no obligatorio.
La región del proxy se establece mediante la configuración de la cuenta de Scrapeless: la herramienta browser_create de MCP no expone un argumento proxyCountry por llamada. Para flujos de trabajo que necesitan control de región por consulta (resultados de mapas de EE. UU. frente a ES frente a JP), utiliza directamente la CLI scrapeless-scraping-browser con --proxy-country, o ejecuta múltiples claves API de Scrapeless configuradas para diferentes regiones.
Si la llamada devuelve un error de conexión transitoria, pide al agente que lo intente de nuevo una vez. La piscina de proxy ocasionalmente no devuelve ninguna IP residencial disponible en el momento de la asignación; un browser_create fresco tiene éxito en el siguiente intento.
Paso 2 — Navegar a la URL de búsqueda de Maps (browser_goto)
Google Maps expone un patrón de URL de enlace profundo para búsquedas: https://www.google.com/maps/search/<query>. Codifica la consulta en la URL, y la página se carga con el feed lateral poblado para esa búsqueda.
json
{
"name": "browser_goto",
"arguments": {
"url": "https://www.google.com/maps/search/coffee+shops+in+Pike+Place+Seattle"
}
}
La forma de URL lleva al agente directamente a un SERP poblado sin necesidad de utilizar el cuadro de búsqueda, lo que mantiene el flujo corto y reduce el área donde el agente podría hacer clic en el control incorrecto.
Manejo de muro de consentimiento. Cuando el navegador en la nube se enrutó a través de un proxy residencial europeo, Google interrumpe la navegación con una pantalla de consentimiento en consent.google.com antes de mostrar Maps. El agente debe llamar a browser_get_text después de browser_goto y verificar si la respuesta contiene "consentimiento" o "Aceptar todo" / equivalentes localizados (Accetta tutto, Akzeptieren, Accepter). Si es así, hace clic en el botón Aceptar utilizando browser_click — las etiquetas accesibles funcionan en todos los locales:
json
{
"name": "browser_click",
"arguments": {
"selector": "button[aria-label*='Accept' i], form[action*='consent'] button:last-of-type"
}
}
Después del clic, repite browser_goto para aterrizar en la página de Maps misma. Los flujos de trabajo que transitan a través de una región de proxy de EE. UU. no suelen chocar con este muro.
Paso 3 — Esperar a que se renderice el feed (browser_wait_for)
El SPA de Maps se pinta en oleadas: primero el lienzo del mapa, luego la shell del feed lateral, y luego las tarjetas de lugar. Espera contra un marcador de tarjeta de lugar antes de extraer, de lo contrario, la región de resultados estará vacía.
json
{
"name": "browser_wait_for",
"arguments": {
"selector": "a.hfpxzc"
}
}
a.hfpxzc es el ancla de enlace de lugar canónica: una por tarjeta orgánica en el feed lateral, con el nombre del lugar en aria-label y la URL canónica /maps/place/<slug>/data=!1s<placeId> en href. Es la señal más fiable de que las tarjetas se han renderizado, ya que el hito del artículo a veces se retrasa detrás de los anclajes de enlace durante la hidratación.
Si el tiempo de espera se agota, la página o bien aterrizó en un intersticial (raro) o el feed está realmente vacío para la consulta. Pide al agente que llame a browser_get_text para volcar el texto visible de la página y así pueda confirmar cuál es el caso.
Paso 4 — Desplazar el feed para cargar más resultados de forma perezosa (browser_scroll, browser_press_key)
El feed lateral inicialmente renderiza aproximadamente de 10 a 20 tarjetas. Lotes subsiguientes se cargan perezosamente a medida que se desplaza el feed, hasta el límite por consulta de aproximadamente 120 lugares.
El servidor MCP expone dos primitivas de desplazamiento:
browser_scroll— desplaza la página, no se requieren parámetros (actúa sobre el documento activo).browser_scroll_to— desplaza a coordenadas absolutas en píxeles. Argumentos requeridos:{x, y}números.
json
{
"name": "browser_scroll",
"arguments": {}
}
Para Google Maps, el feed lateral es su propio contenedor desplazable en lugar de la página misma, por lo que un simple browser_scroll puede no adelantar la carga perezosa. El patrón fiable es enfocar primero el feed con browser_click en cualquier tarjeta renderizada, luego conducir el desplazamiento por teclado con browser_press_key:
json
{
"name": "browser_click",
"arguments": { "selector": "a.hfpxzc:first-of-type" }
}
json
{
"name": "browser_press_key",
"arguments": { "key": "End" }
}
Un flujo típico: haz clic en la primera tarjeta, luego utiliza browser_press_key con "End" o "PageDown" de tres a cinco veces, con un browser_wait de 1500 ms entre pulsaciones de teclas para que la carga perezosa termine antes de que se dispare la siguiente pulsación.
Para raspados profundos, el agente debe monitorizar el conteo de tarjetas después de cada desplazamiento: cuando dos llamadas consecutivas a browser_get_html devuelven el mismo conteo, el feed ha alcanzado el límite por consulta y los desplazamientos posteriores no añaden resultados.
Paso 5 — Extraer las tarjetas de lugar (browser_get_html)
Una vez que el feed ha renderizado el número deseado de tarjetas, obtiene el HTML completo y permite que el agente lo analice.
json
{
"name": "browser_get_html",
"arguments": {}
}
browser_get_html devuelve todo el DOM renderizado como una sola carga de texto; no hay un argumento de selector por región; el agente corta el HTML en memoria después de que la respuesta llega. Cada tarjeta orgánica aparece como un ancla <a class="hfpxzc">; analiza esos para los campos por lugar:
| Campo | Ancla |
|---|---|
name |
aria-label de la tarjeta (la cadena completa comienza con el nombre del lugar) |
rating |
[role="img"][aria-label*="stars"] — aria-label se analiza como "4.8 estrellas" |
reviewCount |
El nodo de texto al lado de la calificación, p.ej. "(3,174)" |
address |
Una línea de texto secundaria en la tarjeta, a menudo después de la categoría |
category |
Primera línea de texto secundaria que no es de calificación |
priceLevel |
Un token corto de caracteres $ cuando está presente |
mapUrl |
a.hfpxzc[href] — la URL canónica del lugar |
placeId |
Analizado desde el mapUrl a través del segmento !1s0x<hex>:0x<hex> |
isSponsored |
La tarjeta contiene [aria-label="Patrocinado"] |
placeId es la clave de deduplicación que soporta la carga cuando se ejecuta la misma consulta en múltiples sesiones o mosaicos.
Paso 6 — Opcional: profundizar en el panel de detalles (browser_click + browser_get_html)
Para cada lugar, el agente puede hacer clic en la tarjeta para abrir el panel de detalles, luego extraer campos más ricos: dirección completa, número de teléfono, sitio web, horarios de apertura y las últimas reseñas.
json
{
"name": "browser_click",
"arguments": {
"selector": "a.hfpxzc[href*=\"<placeId>\"]"
}
}
Después del clic, espera a que se renderice el hito del panel de detalles:
json
{
"name": "browser_wait_for",
"arguments": {
"selector": "h1.DUwDvf"
}
}
h1.DUwDvf es el encabezado del nombre del lugar dentro del panel de detalles — es la señal más clara de que el panel se ha pintado completamente. Luego llama a browser_get_html contra el panel y analiza:
| Campo | Ancla |
|---|---|
placeName |
h1.DUwDvf (el texto interno — elimina los <span> anidados si están presentes) |
address |
button[data-item-id="address"] — dirección completa en aria-label, formato "Dirección: <calle>, <ciudad>, …" (etiqueta localizada) |
phone |
button[data-item-id^="phone:tel:"] — el número de teléfono está incrustado en el valor data-item-id (p.ej. phone:tel:+14252437356) y también aparece en aria-label |
website |
a[data-item-id="authority"] — el sitio web es un ancla (<a>), no un botón; extrae el atributo href |
hours |
Filas por día: button[jsaction*="openhours"], cada una con aria-label="<día de la semana>,<abrir>~<cerrar>, <etiqueta-copia>" (un botón por día de la semana) |
reviews |
.jftiEf tarjetas de reseñas — nombre del revisor, calificación, contenido, fecha, respuesta del propietario |
Profundizar en el panel aumenta el costo de la solicitud por lugar; solo hazlo cuando el flujo realmente necesite los campos exclusivos del panel.
Paso 7 — Capturar captura de pantalla (browser_screenshot)
Una captura de pantalla es útil para la regresión visual, recopilación de evidencia de quejas o verificación de extremo a extremo. El agente llama a browser_screenshot en cualquier punto del flujo y obtiene una imagen.
json
{
"name": "browser_screenshot",
"arguments": {
"fullPage": true
}
}
Para Google Maps, la captura de pantalla de toda la página incluye tanto el feed lateral como el lienzo del mapa. Para una captura de pantalla solo del feed, desplaza el feed de regreso a la parte superior y toma una captura de pantalla del tamaño del viewport en su lugar.
Paso 8 — Cerrar la sesión (browser_close)
Cuando el agente ha terminado, llama a browser_close para liberar el navegador en la nube. La herramienta requiere el sessionId devuelto por browser_create:
json
{
"name": "browser_close",
"arguments": {
"sessionId": "vybp-a64d-2dqf-9vsq86"
}
}
Liberar la sesión rápidamente mantiene limpio el conteo de sesiones concurrentes de la cuenta y es el comportamiento predeterminado correcto al final de cada raspado.
Escalando más allá del límite por consulta
Google Maps limita una búsqueda única a aproximadamente 120 lugares. Para consultas que exceden eso — "cada restaurante en Manhattan", "todos los dentistas en California" — la estrategia es una cuadrícula geográfica:
- Dividir el área de búsqueda en cuadros delimitadores más pequeños. Un vecindario, un código postal, o un cuadrado de 2 km × 2 km típicamente devuelve mucho menos de 120 resultados, por lo que cada mosaico se agota completamente.
- Ejecutar una consulta por mosaico. Ya sea incorporando un segmento de
@lat,lng,zoomen la URL de Maps (p.ej.https://www.google.com/maps/search/coffee/@47.6097,-122.3331,15z) o cambiando la cadena de consulta ("tiendas de café en Pike Place" → "tiendas de café en Belltown" → "tiendas de café en Capitol Hill"). - Desduplicar entre los mosaicos por
placeId. Un solo lugar puede aparecer en mosaicos superpuestos; elplaceIdanalizado de lamapUrl(!1s0x<hex>:0x<hex>) es la clave de unión estable.
El mismo patrón se compone a partir de los primitivas de MCP: una browser_create + una browser_goto + desplazamiento + extracción por mosaico, con el agente manteniendo el conjunto de desduplicación entre mosaicos en la memoria de la conversación.
Lo Que Obtienes
Las herramientas de MCP devuelven texto en bruto (HTML, texto de la página, capturas de pantalla); la forma JSON es lo que el agente ensambla. Para una sola pasada de búsqueda y desplazamiento con la plantilla descubrir → extraer mencionada anteriormente, el esquema se ve así:
json
// El esquema refleja lo que el agente emite cuando se le solicita extraer tarjetas de lugar.
// Los valores de los campos son muestras ilustrativas.
{
"query": "cafés en Pike Place Seattle",
"queryUrl": "https://www.google.com/maps/search/cafés+en+Pike+Place+Seattle",
"resultsReturned": 15,
"results": [
{
"name": "Storyville Coffee Pike Place",
"rating": 4.8,
"reviewCount": 3174,
"address": "94 Pike St #34, Seattle, WA 98101",
"category": "Cafetería",
"priceLevel": "$$",
"mapUrl": "https://www.google.com/maps/place/Storyville+Coffee+Pike+Place/data=!4m7!3m6!1s0x54906ab2f0c61d05:0x771b2a7dce963d58!8m2!3d47.60895!4d-122.3404309",
"placeId": "0x54906ab2f0c61d05:0x771b2a7dce963d58",
"isSponsored": false,
"phone": null,
"website": null,
"hours": null
}
]
}
Unas pocas observaciones honestas sobre esta salida, que vale la pena conocer antes de ejecutar a gran escala:
- Tiempo de hidratación. La SPA de Maps se renderiza en oleadas: el lienzo del mapa, luego la estructura de la feed, luego las tarjetas. Un
browser_wait_forcontraa.hfpxzces lo que controla la extracción. Si el primerbrowser_get_htmldel agente devuelve solo la estructura, pídale que espere un poco más y vuelva a extraer. - Estabilidad del selector.
[role="article"],[role="feed"], cadenasaria-labelen los widgets de calificación, ya.hfpxzc[href]para elmapUrlcanónico son los anclajes de mayor duración. Los nombres de clase (por ejemplo,h1.DUwDvf,.jftiEf) funcionan hoy, pero rotan en las implementaciones; trátalos como mejor esfuerzo y vuelve a ejecutar una pasada de descubrimiento si un futuro raspado regresa vacío. - Ubicación patrocinada. Las tarjetas patrocinadas se entrelazan con los resultados orgánicos y llevan
[aria-label="Sponsored"]. El agente debería establecerisSponsoreden lugar de descartarlas, para que los consumidores posteriores puedan filtrar explícitamente. - Los campos del panel de detalles son condicionales. Teléfono, sitio web y horarios provienen de filas
button[data-item-id="…"]que no existen en todos los lugares. Trátalos como anulables en lugar de requeridos. - Locale y lenguaje. El texto de la interfaz en las tarjetas de lugar (las etiquetas del botón
"hours","reviews","website") se localiza al idioma del país del proxy. Para consultas de salida de EE. UU., las etiquetas están en inglés; para ES, FR, JP, las expresiones regulares del analizador deben coincidir con las cadenas localizadas o el campo vuelve nulo. - Límite por consulta. Aproximadamente 120 resultados por consulta en la feed lateral. Para geografías más grandes, utiliza el patrón de mosaicos de cuadrícula geográfica anterior y desduplica por
placeId.
Preguntas Frecuentes
Q1: ¿Necesito un proxy para Google Maps y puedo elegir la región?
Cada sesión de navegador en la nube enrutará automáticamente a través de un proxy residencial sin necesidad de configuración de proxy separada para que la llamada funcione. Sin embargo, la región del proxy se establece a nivel de cuenta y no se expone como un argumento por llamada en la herramienta browser_create de MCP. Los flujos de trabajo que necesiten control de región por consulta (resultados de mapas de EE. UU. vs ES vs JP) deberían dirigir el navegador en la nube a través de la CLI scrapeless-scraping-browser (que expone --proxy-country) o mantener múltiples claves API de Scrapeless configuradas para diferentes regiones predeterminadas.
Q2: ¿Cuál es la diferencia entre el modo stdio y el modo HTTP transmitible?
El modo stdio ejecuta npx scrapeless-mcp-server como un proceso hijo del cliente de MCP (Claude Desktop, Cursor, etc.) y es el valor predeterminado correcto para agentes de escritorio. El modo HTTP transmitible apunta al cliente a https://api.scrapeless.com/mcp y es el valor predeterminado correcto para agentes alojados en la nube que no pueden salir a npx. Ambos modos utilizan la misma clave API de Scrapeless.
Q3: ¿Cómo paso del límite de 120 resultados en una consulta?
Divide el área de búsqueda en geografías más pequeñas (barrios, códigos postales, cajas delimitadoras de lat/lng) y ejecuta una consulta por mosaico. Utiliza el placeId analizado (del segmento !1s0x<hex>:0x<hex> de la mapUrl) para desduplicar entre mosaicos superpuestos. El patrón de cuadrícula geográfica está documentado en la sección Escalando más allá del límite por consulta mencionada anteriormente.
Q4: ¿Puedo extraer reseñas de un lugar?
Sí. Después de que se renderiza la feed, haz clic en la tarjeta para abrir el panel de detalles, espera a h1.DUwDvf, luego extrae tarjetas de reseñas de la región .jftiEf — título, autor, calificación, cuerpo y fecha. La extracción es por lugar y aumenta el costo de la solicitud; solo házlo cuando el flujo de trabajo necesite la carga de reseñas.
Q5: ¿Qué sucede cuando Google Maps cambia el DOM?
Reejecutar un pase de descubrimiento: pida al agente que llame a browser_get_html en la región relevante y reidentifique los anclajes estables actuales. [role="article"], [role="feed"], cadenas aria-label y a.hfpxzc[href] son los que tienen mayor longevidad; los nombres de clase rotan. El patrón de descubrimiento → extracción de la habilidad maneja esto sin cambios en el código.
Q6: ¿Por qué mi sesión a veces devuelve Access Denied o una página CAPTCHA?
Una nueva asignación de proxy ocasionalmente cae en una IP señalada. Pida al agente que llame a browser_close y luego browser_create nuevamente para crear una nueva sesión. Las asignaciones posteriores tienen éxito.
Q9: ¿Pueden varios agentes compartir un mismo servidor MCP?
Cada cliente consciente de MCP se conecta a su propia instancia de servidor (en modo stdio) o al punto final HTTP compartido (en modo transmitible). Las sesiones están aisladas por el taskId devuelto de browser_create, por lo que varios agentes que llaman al mismo servidor MCP no comparten cookies ni estado de desplazamiento. Para rastrillados de alta dispersión, genere una sesión por consulta en lugar de reutilizar una única sesión de larga duración.
Q10: ¿Con qué clientes MCP funciona esto?
Cualquier cliente que soporte MCP. El protocolo es el contrato: la lista de herramientas del servidor y la forma de llamada son idénticas en todos los clientes. El paso 2 incluye rutas de configuración para Claude Desktop, Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI y VS Code + GitHub Copilot Chat; el mismo fragmento JSON mcpServers se puede usar en clientes personalizados de Python o Node construidos con el MCP TypeScript SDK, y el punto final HTTP transmitible en https://api.scrapeless.com/mcp funciona con cualquier cliente HTTP.
Q11: ¿El servidor MCP tiene una herramienta de Google Maps dedicada?
No, el servidor proporciona primitivas de navegador genéricas (browser_create, browser_goto, browser_wait_for, browser_get_html, browser_get_text, browser_click, browser_type, browser_press_key, browser_scroll, browser_scroll_to, browser_screenshot, browser_snapshot, browser_close) más los ayudantes a nivel de página (scrape_html, scrape_markdown, scrape_screenshot) y herramientas de datos de Google (google_search, google_trends). El agente compone el raspado de Maps a partir de las primitivas del navegador; las mismas primitivas impulsan Amazon, Home Depot, Etsy y cualquier otro sitio pesado en JavaScript.
Q12: ¿Por qué Maps carga una página de consentimiento en lugar de los resultados de búsqueda?
Cuando la sesión del navegador en la nube se enruta a través de un proxy residencial europeo, Google interrumpe la navegación con un intersticial de consent.google.com antes de mostrar Maps. El agente debe llamar a browser_get_text después de browser_goto y, si la respuesta contiene "consent" o una etiqueta de botón Aceptar (Accept all / Accetta tutto / Akzeptieren / Accepter), hacer browser_click en el botón antes de volver a intentar la navegación. El paso 2 cubre el fragmento completo.
Q13: ¿Por qué mi sesión a veces devuelve un error de conexión transitorio como os error 10054 o 503?
El grupo de proxies residenciales de Scrapeless ocasionalmente devuelve un error de asignación de corta duración en browser_create. Un solo intento de reintento suele tener éxito: envuelva browser_create en un bucle de reintentos de 2 a 3 intentos en el código de producción, o simplemente pida al agente que vuelva a intentar una vez.
Q14: ¿Cuántos trabajos de raspado MCP puedo ejecutar simultáneamente?
Para fiabilidad, mantenga un cliente MCP a una sesión en vuelo a la vez y encadene llamadas dentro de un solo turnos del agente. Para una mayor dispersión, ejecute varios clientes MCP (o procesos trabajadores que acceden al punto final HTTP transmitible) y limite la concurrencia a ≤ 3 sesiones por host. Para trabajos por lotes de puro rendimiento (más de 10,000 consultas/hora), conduzca el scrapeless-scraping-browser CLI directamente con un grupo de trabajadores en paralelo; el camino de MCP es el mejor para el descubrimiento impulsado por el agente y la cobertura geográfica basada en losetas.
Q15: ¿Puedo ejecutar esto sin un cliente MCP?
Sí. Dos rutas: (1) llame al punto final HTTP transmitible en https://api.scrapeless.com/mcp directamente desde cualquier cliente HTTP con el encabezado x-api-token; (2) controle el navegador en la nube a través del scrapeless-scraping-browser CLI a través de bash. El flujo de trabajo impulsado por MCP es la ruta recomendada para el raspado impulsado por el agente; el CLI es el camino correcto para pipelines de lotes guionados.
Q16: ¿Por qué usar una URL canónica /maps/search/<query> en lugar de impulsar la caja de búsqueda?
La URL de búsqueda de enlace profundo lleva al agente directamente a un SERP poblado sin necesidad de hacer clic en la entrada de búsqueda, escribir y presionar Enter. Menos llamadas a herramientas, menos posibilidades de que el agente haga clic en el control incorrecto, ejecución más rápida de extremo a extremo. El mismo enfoque para las URL de lugares: navegue directamente a /maps/place/<slug>/data=!1s<placeId> en lugar de impulsar búsqueda-luego-clic cuando el placeId ya es conocido.
En Scrapeless, solo accedemos a datos disponibles públicamente y cumplimos estrictamente con las leyes, regulaciones y políticas de privacidad del sitio web aplicables. El contenido de este blog es sólo para fines de demostración y no implica ninguna actividad ilegal o infractora. No ofrecemos garantías y renunciamos a toda responsabilidad por el uso de la información de este blog o enlaces de terceros. Antes de realizar cualquier actividad de scraping, consulte a su asesor legal y revise los términos de servicio del sitio web de destino u obtenga los permisos necesarios.



