Como raspar o Google Maps em grande escala com agente de IA e servidor Scrapeless MCP
Advanced Bot Mitigation Engineer
Principais Conclusões:
- Funciona em qualquer cliente que suporte MCP. O Servidor MCP Scrapeless expõe o navegador na nuvem como um conjunto de ferramentas do Protocolo de Contexto de Modelo — Claude Desktop, Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI, VS Code + GitHub Copilot Chat ou um cliente personalizado construído com o MCP TypeScript SDK chamam-nas da mesma forma. O protocolo é o que suporta a carga, não o cliente. Sem cola de SDK, sem gerenciamento de subprocessos CLI.
- Primitivas do navegador se combinam em um scraper do Google Maps. O servidor fornece ferramentas 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— e o agente as monta no fluxo de busca → rolagem → extração que o Google Maps requer. - Dois modos de transporte. O modo Stdio executa o servidor localmente via
npx scrapeless-mcp-servere é o padrão certo para clientes MCP de desktop em uma estação de trabalho. O modo HTTP streaming aponta o cliente parahttps://api.scrapeless.com/mcpe é o padrão certo para agentes hospedados na nuvem. - Renderização em nuvem e proxies residenciais. O Google Maps é um SPA pesado em JavaScript que carrega resultados de forma preguiçosa como um feed. O Scrapeless Scraping Browser lida com a renderização JS, saída por proxy residencial e impressão digital anti-detecção em cada sessão — o agente só precisa controlar a página. As sessões alocam-se através da região do proxy para a qual a conta Scrapeless está configurada; nenhuma substituição de região por chamada é exposta na superfície da ferramenta MCP hoje.
- Limite de resultados por consulta. O Google Maps mostra até 120 resultados por consulta no feed lateral. Para além disso, a estratégia é uma grade geográfica: dividir a área de busca em caixas delimitadoras menores, executar uma consulta por caixa e deduplicar por id de local.
- Gratuito para começar. Novas contas Scrapeless incluem execução gratuita do Scraping Browser — inscreva-se em Scrapeless.
Introdução: um caminho nativo de MCP para dados do Google Maps
O Google Maps é um dos conjuntos de dados empresariais públicos mais ricos na web — nomes, endereços, classificações, contagem de avaliações, horários de funcionamento, links para fotos, tags de categoria, detalhes de contato e um id de local estável para cada entrada. Para equipes de SEO local, pipelines de geração de leads, analytics imobiliário e mapeamento de localização de concorrentes, esse conjunto de dados é a base do fluxo de trabalho.
A página em si é difícil de controlar sem um navegador real. A visualização do mapa carrega seu próprio SDK, o painel lateral pagina carregando de forma preguiçosa enquanto o feed rola, painéis de detalhes de locais individuais se abrem através de cliques do usuário, e a contagem de resultados se limita a cerca de 120 por consulta. O scraping puramente HTTP retorna o shell JS; os dados vivem atrás do DOM renderizado.
Este post orienta sobre como usar o Servidor MCP Scrapeless com qualquer cliente ciente de MCP — Claude Desktop, Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI ou um cliente personalizado construído contra o MCP TypeScript SDK — para raspar o Google Maps de ponta a ponta. O servidor envolve o Scrapeless Scraping Browser — um navegador em nuvem pronto para agentes — como um conjunto de ferramentas MCP, então o agente chama browser_create / browser_goto / browser_scroll / browser_get_html diretamente através do protocolo em vez de chamar um CLI ou conectar um SDK. O navegador em nuvem lida com a renderização, os proxies e a camada anti-detecção; o agente lida com o padrão descobrir → extrair.
Para o mesmo alvo através de uma superfície de integração diferente, veja o post do agente LangChain ou, para a versão CLI bash, o post mais amplo motores de busca.
O Que Você Pode Fazer Com Isso
- Geração de leads local. Extrair todos os dentistas, encanadores ou cafeterias em uma cidade alvo com nome, endereço, telefone, site, horários, classificação e contagem de avaliações.
- Análise competitiva de SEO local. Monitorar a classificação de localização de concorrentes em consultas de palavras-chave de categoria e as listagens ao redor na mesma SERP.
- Construção de conjuntos de dados de imóveis e POI. Criar tabelas de pontos de interesse categorizadas — restaurantes por tipo de cozinha, cadeias de varejo por região, serviços públicos por CEP — atualizadas em um ciclo contínuo.
- Monitoramento de reputação. Capturar a classificação por local, contagem de avaliações e velocidade de avaliações em uma marca com várias localizações para destacar os locais fora da curva.
- Pesquisa de mercado. Mapear a densidade e a mistura de categorias de pequenas empresas em uma área alvo para estimar a saturação do mercado.
- Inteligência de fotos e preços. Capturar screenshots do painel de locais para regressão visual, ou extrair o indicador de nível de preço (
$,$$,$$$) por listagem.
Por que o Navegador de Scraping sem Resíduos
O Navegador de Scraping sem Resíduos é um navegador em nuvem personalizável e anti-detecção, projetado para rastreadores da web e agentes de IA. Para o Google Maps especificamente, ele traz:
- Renderização de JavaScript do lado da nuvem para que o SDK do mapa, o feed lateral, o carregamento sob demanda impulsionado pela rolagem e o painel de detalhes do local sejam preenchidos antes da extração.
- Proxies residenciais em mais de 195 países para que consultas geobaseadas retornem os anúncios que um usuário local veria — importante porque os resultados do Google Maps variam de acordo com a região de saída.
- Impressão digital anti-detecção em cada sessão, assim a página é renderizada de forma idêntica ao tráfego orgânico durante longas sessões de rolagem.
- Persistência de sessão via o id da tarefa
browser_create; chamadas subsequentes de ferramentasbrowser_*no mesmo agente reutilizam o mesmo navegador em nuvem, mantendo os cookies, a posição de rolagem e o histórico de navegação consistentes. - Uma única superfície MCP — cada operação que o agente precisa para operar o Maps (
browser_goto,browser_wait_for,browser_scroll,browser_click,browser_get_html,browser_get_text,browser_screenshot) está a uma chamada de ferramenta de distância.
Obtenha sua chave API no plano gratuito em Scrapeless. A documentação completa da superfície de ferramentas MCP está em github.com/scrapeless-ai/scrapeless-mcp-server.
Pré-requisitos
- Qualquer cliente que suporte MCP. Claude Desktop (claude.com/download), Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI, VS Code + GitHub Copilot Chat, ou um cliente personalizado construído contra o MCP TypeScript SDK — o protocolo é o que suporta a carga, não o cliente.
- Node.js 18 ou mais recente (para o modo de transporte stdio).
- Uma conta Scrapeless e chave API — inscreva-se em Scrapeless.
- Familiaridade básica com a edição do arquivo de configuração MCP do seu cliente.
Instalação
O Servidor MCP Scrapeless é publicado como o pacote npm scrapeless-mcp-server e pode ser chamado de qualquer cliente que suporte o Protocolo de Contexto do Modelo. O caminho de instalação em quatro etapas abaixo mostra o caminho para os clientes mais comuns (Claude Desktop, Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI), mas o trecho JSON em si é portátil — insira-o em qualquer cliente que sua equipe já utiliza e as mesmas chamadas de ferramentas funcionarão.
1. Obtenha sua chave API Scrapeless
Inscreva-se em Scrapeless, abra o painel e, em Configurações → Gerenciamento de Chave API, crie uma chave. Copie o valor — ele vai para a configuração MCP na etapa 2.
Obtenha sua chave API no plano gratuito inscrevendo-se no Scrapeless e participe da comunidade oficial:
Comunidade Oficial do Discord Scrapeless
Comunidade Oficial do Telegram Scrapeless
2. Adicione o servidor MCP ao seu cliente (modo stdio)
A localização do arquivo de configuração depende do cliente:
Claude Desktop (o aplicativo de desktop do claude.com/download):
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Claude Code (o CLI de terminal):
- Todas as plataformas:
~/.claude.json - Ou use o subcomando
claude mcp addem vez de editar o arquivo manualmente:bashclaude mcp add scrapeless --scope user --transport stdio \ --env "SCRAPELESS_KEY=SEU_SCRAPELESS_KEY" \ -- npx -y scrapeless-mcp-server
Cursor: edite ~/.cursor/mcp.json (ou use as Configurações do Cursor → UI MCP). A mesma estrutura JSON que o trecho abaixo.
OpenAI Codex CLI: O Codex lê servidores MCP do ~/.codex/config.toml e também expõe um helper codex mcp. O comando de instalação stdio é:
bash
codex mcp add scrapeless \
--env "SCRAPELESS_KEY=SEU_SCRAPELESS_KEY" \
-- npx -y scrapeless-mcp-server
O equivalente TOML é:
toml
[mcp_servers.scrapeless]
command = "npx"
args = ["-y", "scrapeless-mcp-server"]
[mcp_servers.scrapeless.env]
SCRAPELESS_KEY = "SEU_SCRAPELESS_KEY"
Após editar o arquivo, reinicie o Codex e confirme a entrada com codex mcp list --json. O Codex é rigoroso quanto ao enquadramento MCP stdio: o processo do servidor deve escrever apenas mensagens JSON-RPC para stdout. Se o Codex relatar falha ao conectar-se ao servidor MCP, resposta de inicialização ou conexão fechada, verifique se o servidor imprimiu uma linha de log de inicialização para stdout antes da resposta JSON-RPC. Atualize para uma versão corrigida do servidor ou execute o servidor atrás de um pequeno filtro stdio que redirecione linhas stdout não JSON para stderr.
Use o modo stdio como o caminho padrão do Codex. As versões atuais do Codex CLI expõem codex mcp add --url para servidores HTTP transmitíveis, mas a opção de autenticação embutida do helper é baseada em token bearer, enquanto o endpoint MCP hospedado do Scrapeless espera o cabeçalho x-api-token. Use o modo HTTP do Codex somente se a sua versão/configuração do Codex suportar cabeçalhos HTTP personalizados para servidores MCP.
Gemini CLI: Gemini suporta servidores MCP através de mcpServers em settings.json, além de um helper gemini mcp. O próprio Gemini CLI atualmente requer Node.js 20 ou mais recente. Para uma instalação stdio para todos os usuários, execute:
bash
gemini mcp add -s user \
-e SCRAPELESS_KEY=SUA_CHAVE_SCRAPELESS \
scrapeless npx -y scrapeless-mcp-server
Ou edite diretamente ~/.gemini/settings.json:
json
{
"mcpServers": {
"scrapeless": {
"command": "npx",
"args": ["-y", "scrapeless-mcp-server"],
"env": {
"SCRAPELESS_KEY": "SUA_CHAVE_SCRAPELESS"
}
}
}
}
Use .gemini/settings.json em vez disso para configuração limitada ao projeto. Confirme com gemini mcp list (ou gemini --debug mcp list se sua shell não interativa não imprimir nenhuma tabela), ou inicie o Gemini e execute /mcp para ver o status da conexão e as ferramentas descobertas.
VS Code + GitHub Copilot Chat: o mesmo trecho mcpServers vai nas configurações MCP em nível de espaço de trabalho ou de usuário; consulte a documentação do GitHub Copilot Chat MCP para o caminho ativo.
Adicione a entrada do servidor Scrapeless sob mcpServers:
json
{
"mcpServers": {
"scrapeless": {
"type": "stdio",
"command": "npx",
"args": ["-y", "scrapeless-mcp-server"],
"env": {
"SCRAPELESS_KEY": "SUA_CHAVE_SCRAPELESS"
}
}
}
}
Substitua SUA_CHAVE_SCRAPELESS pela chave do passo 1. Reinicie o cliente para pegar o novo servidor. Na primeira execução, npx -y scrapeless-mcp-server baixa o pacote e inicia o servidor via stdio — nenhum comando de instalação separado é necessário. Após a reinicialização, o painel MCP do cliente deve listar scrapeless juntamente com quaisquer outros servidores conectados.
3. Ou use o modo HTTP transmitível (agentes hospedados na nuvem)
Para agentes que executam remotamente — um servidor Cursor hospedado, um runner CI, um cliente MCP customizado rodando em um contêiner — aponte o cliente para o endpoint MCP hospedado pelo Scrapeless em vez de executar npx localmente:
json
{
"mcpServers": {
"Scrapeless MCP Server": {
"type": "streamable-http",
"url": "https://api.scrapeless.com/mcp",
"headers": {
"x-api-token": "SUA_CHAVE_SCRAPELESS"
},
"disabled": false,
"alwaysAllow": []
}
}
}
A mesma SUA_CHAVE_SCRAPELESS funciona em ambos os modos. O transporte HTTP é o padrão correto quando um binário stdio não pode ser executado junto com o agente (caixas de arejamento CI, executores de agentes hospedados).
Para o Gemini CLI, o helper HTTP e a estrutura JSON são:
bash
gemini mcp add -s user -t http \
-H "x-api-token: SUA_CHAVE_SCRAPELESS" \
scrapeless https://api.scrapeless.com/mcp
json
{
"mcpServers": {
"scrapeless": {
"httpUrl": "https://api.scrapeless.com/mcp",
"headers": {
"x-api-token": "SUA_CHAVE_SCRAPELESS"
}
}
}
}
4. Verifique se o servidor MCP está configurado corretamente
Antes do primeiro scrape real do Maps, teste a instalação com uma solicitação:
"Use o servidor MCP do Scrapeless para abrir https://example.com e me diga o título da página."
O agente deve chamar browser_create para criar uma sessão, depois browser_goto para navegar, em seguida browser_get_text (ou browser_get_html) e responder com "Exemplo de Domínio". Se isso voltar, o servidor MCP está carregado, a chave da API está configurada e o navegador na nuvem é acessível.
Se falhar:
| Sintoma | Causa Provável | Correção |
|---|---|---|
| "Não vejo uma ferramenta Scrapeless" | Servidor MCP não carregado pelo cliente | Verifique novamente o caminho do arquivo de configuração, reinicie o cliente, procure o servidor no indicador MCP do cliente |
Falha na autenticação / 401 |
Chave da API não configurada ou expirada | Recopia a chave do painel, cole-a na configuração, reinicie o cliente |
npx trava na primeira execução |
Rede lenta ou tempo limite do registro | Execute npx -y scrapeless-mcp-server uma vez em um terminal para pré-cachear o pacote, depois reinicie o cliente |
Codex diz initialize response ou connection closed durante a inicialização do MCP |
O servidor stdio escreveu texto não-JSON no stdout antes do handshake JSON-RPC do MCP | Atualize o servidor ou envolva-o para que apenas linhas JSON-RPC cheguem ao stdout e os logs vão para stderr |
Chamada de ferramenta retorna HTML Acesso Negado |
Pool de proxy ou desafio anti-bot em uma nova alocação | Peça ao agente para tentar novamente — browser_close então browser_create cria uma nova sessão |
Como usar isso: converse com seu agente
Após a instalação, você raspa o Google Maps conversando com seu agente — não codificando manualmente as chamadas das ferramentas. O servidor MCP expõe o navegador na nuvem como uma lista de ferramentas descobríveis; o agente lê as descrições das ferramentas e as compõe na sequência correta com base na solicitação.
Solicitações que você pode colar
| O que você diz ao seu agente | O que você recebe de volta |
|---|---|
| "Obtenha as 30 melhores cafeterias em Pike Place, Seattle, do Google Maps. Retorne JSON com nome, classificação, contagem de avaliações e endereço." | Um registro JSON por local com os campos solicitados |
| "Liste todos os dentistas no CEP 90015 com telefone, site e horário." | JSON por local com contato + carga horária |
| "Pesquise no Google Maps por 'restaurantes de sushi perto da Brooklyn Bridge', role a feed até o final, retorne tudo." | Até ~120 locais, sem duplicatas por nome + endereço |
| "Para cada resultado, também clique no painel de detalhes e extraia a URL do site e o endereço completo." | JSON por local enriquecido com campos do painel de detalhes |
| "Tire um print da página de resultados da pesquisa após rolar." | Captura de tela + JSON extraído |
| "Encontre restaurantes italianos em 'São Francisco'. Filtre para os que têm classificação ≥ 4.5 e pelo menos 200 avaliações." | Lista de locais filtrados |
| "Execute a mesma consulta a partir de um IP de Madrid — retorne os resultados do Maps como um usuário espanhol os veria." | Resultados cientes da localização (rotas sem scrap através de um proxy residencial ES) |
| "Para o local chamado 'Storyville Coffee Pike Place', abra o painel do local e extraia as 10 últimas avaliações." | Carga de avaliações do painel de detalhes |
Exemplo prático: melhores cafeterias em Pike Place, Seattle
Você digita:
"Use o Scrapeless MCP para raspar o Google Maps por 'cafeterias em Pike Place Seattle'. Retorne nome, classificação, contagem de avaliações, endereço e URL do local para os 15 melhores resultados. Formate como JSON."
O plano do agente (em inglês simples):
- Chame
browser_createpara criar uma sessão de navegador em nuvem.- Chame
browser_gotocom a URL de busca do Mapshttps://www.google.com/maps/search/cafeterias+em+Pike+Place+Seattle.- Se a resposta mostrar um intersticial de
consent.google.com, chamebrowser_clickembutton[aria-label*='Aceitar' i](ou o equivalente localizado) para dispensá-lo antes de continuar.- Chame
browser_wait_forcontraa.hfpxzc— o âncora do link do local canônico — para que a extração ocorra contra os cartões renderizados em vez do shell do SDK.- Para puxar mais do que os primeiros ~10–20 cartões, chame
browser_clickno primeiro cartão para focar a feed, entãobrowser_press_keycomEnd(ouPageDown) várias vezes para carregar em lotes adicionais de forma preguiçosa.- Chame
browser_get_htmlpara retornar o DOM renderizado completo, então analise cada<a class="hfpxzc">para os campos por local.- Chame
browser_closecom o id da sessão para liberar o navegador em nuvem.
O que você recebe de volta (saída ilustrativa, valores de amostra):
json
{
"query": "cafeterias em Pike Place Seattle",
"resultsReturned": 7,
"results": [
{
"name": "Storyville Coffee Pike Place",
"placeId": "0x54906ab2f0c61d05:0x771b2a7dce963d58",
"mapUrl": "https://www.google.com/maps/place/Storyville+Coffee+Pike+Place/data=!4m7!3m6!1s0x54906ab2f0c61d05:0x771b2a7dce963d58!8m2!3d47.60895!4d-122.3404309",
"isSponsored": false
},
{
"name": "Pike Street Coffee",
"placeId": "0x54906bb5338baf2f:0x51e2d4b19d7cfe40",
"mapUrl": "https://www.google.com/maps/place/Pike+Street+Coffee/data=!4m7!3m6!1s0x54906bb5338baf2f:0x51e2d4b19d7cfe40!8m2!3d47.6083904!4d-122.3415875",
"isSponsored": false
},
{
"name": "Ghost Alley Espresso",
"placeId": "0x54906ab258bb013d:0xba2ef7762e477551",
"mapUrl": "https://www.google.com/maps/place/Ghost+Alley+Espresso/data=!4m7!3m6!1s0x54906ab258bb013d:0xba2ef7762e477551!8m2!3d47.6086076!4d-122.340581",
"isSponsored": false
}
/* … 4 mais locais com a mesma estrutura (Anchorhead Coffee, The Crumpet Shop, Le Panier, Starbucks Coffee Company) */
]
}
Os campos name, placeId e mapUrl vêm diretamente do aria-label e href da âncora <a class="hfpxzc">. A classificação, contagem de avaliações, endereço, categoria e nível de preço também estão presentes na marcação do cartão renderizado — o agente os extrai do <div> circundante uma vez que os cartões tenham hidratado. Os campos apenas do painel de detalhes (telefone, site, horários) requerem o clique de perfuração do Passo 6.
Essa é toda a superfície voltada ao usuário para essa raspagem. As chamadas da ferramenta sob o capô nos Passos 1–7 abaixo são o que o agente percorre pelo servidor MCP — você não precisa digitar nenhuma delas.
Formatando prompts: como controlar o que vem de volta
| Fraseado | Efeito |
|---|---|
| "…retornar JSON" / "…como CSV" | Formato de saída |
| "…campos: nome, classificação, apenas endereço" | Restringe os campos que o agente extrai |
| "…os 30 melhores" / "…todos os resultados" | Limita ou remove a truncagem |
| "…classificação ≥ 4.5 e contagem de avaliações ≥ 200" | Aciona um filtro pós-extração |
| "…clique em cada painel de detalhes para o site + avaliação completa" | Aciona a perfuração por local |
| "…de um IP de Madrid" | Roteia através de um proxy residencial ES |
| "…tire um print primeiro" | Captura um browser_screenshot para verificação visual |
| "…tile por esses cinco bairros" | Aciona o padrão de subconsulta por área |
Passo 1 — Crie uma sessão de navegador em nuvem (browser_create)
A ferramenta browser_create aloca um novo navegador em nuvem e retorna um id de sessão que o agente usa para o restante do fluxo. A sessão é a unidade de estado — cookies, posição de rolagem, histórico de navegação tudo reside dentro dela.
Chamada da ferramenta (o que o agente envia através do MCP):
json
{
"name": "browser_create",
"arguments": {}
}
A ferramenta retorna um payload como Nova sessão de navegador criada com ID: vybp-a64d-2dqf-9vsq86. As chamadas subsequentes browser_* no mesmo agente reutilizam a sessão ativa automaticamente; passar o id retornado de volta como sessionId é suportado, mas não obrigatório.
A região do proxy é definida pela configuração da conta Scrapeless — a ferramenta browser_create do MCP não expõe um argumento proxyCountry por chamada. Para fluxos que necessitam de controle de região por consulta (resultados de Mapas dos EUA vs ES vs JP), use diretamente o scrapeless-scraping-browser CLI com --proxy-country, ou execute várias chaves da API Scrapeless configuradas para diferentes regiões.
Se a chamada retornar um erro de conexão transitório, peça ao agente para tentar novamente uma vez. O pool de proxies ocasionalmente não retorna um IP residencial disponível durante a alocação; um novo browser_create é bem-sucedido na próxima tentativa.
Passo 2 — Navegar para a URL de busca do Maps (browser_goto)
O Google Maps expõe um padrão de URL para buscas: https://www.google.com/maps/search/<query>. Codifique a query em URL, e a página será carregada com o feed lateral preenchido para essa busca.
json
{
"name": "browser_goto",
"arguments": {
"url": "https://www.google.com/maps/search/coffee+shops+in+Pike+Place+Seattle"
}
}
A forma do URL leva o agente diretamente a um SERP preenchido sem precisar usar a caixa de busca, o que mantém o fluxo curto e reduz a área de superfície onde o agente pode clicar no controle errado.
Tratamento da parede de consentimento. Quando o navegador em nuvem passa por um proxy residencial europeu, o Google interrompe a navegação com uma tela de consentimento em consent.google.com antes de mostrar os Mapas. O agente deve chamar browser_get_text após browser_goto e verificar se a resposta contém "consentimento" ou "Aceitar tudo" / equivalentes localizados (Accetta tutto, Akzeptieren, Accepter). Se sim, clique no botão Aceitar — rótulos acessíveis funcionam em diferentes locais:
json
{
"name": "browser_click",
"arguments": {
"selector": "button[aria-label*='Accept' i], form[action*='consent'] button:last-of-type"
}
}
Após o clique, repita browser_goto para acessar a página dos Mapas em si. Fluxos que passam por uma região de proxy dos EUA geralmente não encontram essa parede.
Passo 3 — Aguardar o feed ser renderizado (browser_wait_for)
O SPA do Maps pinta em ondas: primeiro a tela do mapa, depois a estrutura do feed lateral, depois os cartões dos locais. Aguarde um marco de cartão de local antes de extrair; caso contrário, a região de resultado estará vazia.
json
{
"name": "browser_wait_for",
"arguments": {
"selector": "a.hfpxzc"
}
}
a.hfpxzc é o âncora de link de local canônico — um por cartão orgânico no feed lateral, com o nome do local em aria-label e a URL canônica /maps/place/<slug>/data=!1s<placeId> em href. É o sinal mais confiável de que os cartões foram renderizados, já que o marco do artigo às vezes fica atrás dos âncoras de link durante a hidratação.
Se o tempo de espera expirar, a página caiu em um intersticial (raro) ou o feed está genuinamente vazio para a consulta. Peça ao agente para chamar browser_get_text para despejar o texto visível da página, para que possa confirmar qual caso é.
Passo 4 — Rolar o feed para carregar mais resultados (browser_scroll, browser_press_key)
O feed lateral inicialmente renderiza cerca de 10–20 cartões. Lotes subsequentes são carregados sob demanda à medida que o feed é rolado, até o limite de aproximadamente 120 locais por consulta.
O servidor MCP expõe dois primitivos de rolagem:
browser_scroll— rola a página, nenhum parâmetro é necessário (atua no documento ativo).browser_scroll_to— rola para coordenadas de pixel absolutas. Argumentos necessários:{x, y}números.
json
{
"name": "browser_scroll",
"arguments": {}
}
Para o Google Maps, o feed lateral é um contêiner rolável em si, em vez da própria página, então um simples browser_scroll pode não avançar a carga sob demanda. O padrão confiável é focar primeiro no feed com browser_click em qualquer cartão renderizado, e então realizar a rolagem do teclado com browser_press_key:
json
{
"name": "browser_click",
"arguments": { "selector": "a.hfpxzc:first-of-type" }
}
json
{
"name": "browser_press_key",
"arguments": { "key": "End" }
}
Um fluxo típico: clique no primeiro cartão, depois browser_press_key com "End" ou "PageDown" três a cinco vezes, com um browser_wait de 1500 ms entre as presses de teclas para que a carga sob demanda termine antes que a próxima pressão ocorra.
Para raspagens profundas, o agente deve monitorar a contagem de cartões após cada rolagem: quando duas chamadas consecutivas de browser_get_html retornam a mesma contagem, o feed atingiu o limite por consulta e novas rolagens não acrescentam resultados.
Passo 5 — Extrair os cartões de lugar (browser_get_html)
Uma vez que o feed tenha renderizado o número desejado de cartões, obtenha o HTML completo e deixe o agente analisá-lo.
json
{
"name": "browser_get_html",
"arguments": {}
}
browser_get_html retorna todo o DOM renderizado como uma única carga de texto — não há argumento de seletor por região; o agente fatiará o HTML na memória após a resposta ser recebida. Cada cartão orgânico aparece como um <a class="hfpxzc"> anexo; analise-os para os campos por lugar:
| Campo | Anexo |
|---|---|
name |
O aria-label do cartão (a string completa começa com o nome do lugar) |
rating |
[role="img"][aria-label*="stars"] — aria-label é analisado como "4.8 estrelas" |
reviewCount |
O nó de texto ao lado da classificação, ex: "(3.174)" |
address |
Uma linha de texto secundária no cartão, geralmente após a categoria |
category |
Primeira linha de texto secundário não relacionada à avaliação |
priceLevel |
Um token curto de caracteres $ quando presente |
mapUrl |
a.hfpxzc[href] — a URL canônica do lugar |
placeId |
Analisado a partir da mapUrl via o segmento !1s0x<hex>:0x<hex> |
isSponsored |
O cartão contém [aria-label="Patrocinado"] |
placeId é a chave de deduplicação essencial ao executar a mesma consulta em várias sessões ou ladrilhos.
Passo 6 — Opcional: aprofundar no painel de detalhes (browser_click + browser_get_html)
Para cada lugar, o agente pode clicar no cartão para abrir o painel de detalhes e então extrair campos mais ricos — endereço completo, número de telefone, website, horários de funcionamento e as últimas avaliações.
json
{
"name": "browser_click",
"arguments": {
"selector": "a.hfpxzc[href*=\"<placeId>\"]"
}
}
Após o clique, aguarde o marco do painel de detalhes ser renderizado:
json
{
"name": "browser_wait_for",
"arguments": {
"selector": "h1.DUwDvf"
}
}
h1.DUwDvf é o cabeçalho do nome do lugar dentro do painel de detalhes — é o sinal mais claro de que o painel foi totalmente desenhado. Em seguida, chame browser_get_html em relação ao painel e analise:
| Campo | Anexo |
|---|---|
placeName |
h1.DUwDvf (o texto interno — remova os <span>s aninhados, se presentes) |
address |
button[data-item-id="address"] — endereço completo da rua no aria-label, formato "Endereço: <rua>, <cidade>, …" (rótulo localizado) |
phone |
button[data-item-id^="phone:tel:"] — número de telefone está embutido no valor de data-item-id (ex: phone:tel:+14252437356) e também aparece no aria-label |
website |
a[data-item-id="authority"] — o website é um anexo (<a>), não um botão; obtenha o atributo href |
hours |
Linhas por dia: button[jsaction*="openhours"], cada uma carregando aria-label="<dia da semana>,<aberto>~<fechado>, <rótulo-copiado>" (um botão por dia da semana) |
reviews |
.jftiEf cartões de avaliação — nome do avaliador, classificação, corpo, data, resposta do proprietário |
Aprofundar aumenta o custo do pedido por lugar; faça isso apenas quando o fluxo realmente precisar dos campos apenas do painel.
Passo 7 — Capturar screenshot (browser_screenshot)
Uma captura de tela é útil para regressão visual, coleta de evidências de reclamação ou verificação de ponta a ponta. O agente chama browser_screenshot em qualquer ponto do fluxo e recebe uma imagem de volta.
json
{
"name": "browser_screenshot",
"arguments": {
"fullPage": true
}
}
Para o Google Maps, a captura de tela da página inteira inclui tanto o feed lateral quanto o canvas do mapa. Para uma captura de tela apenas do feed, role o feed de volta ao topo e tire uma captura de tela do tamanho da viewport.
Passo 8 — Fechar a sessão (browser_close)
Quando o agente terminar, ele chama browser_close para liberar o navegador em nuvem. A ferramenta requer o sessionId retornado por browser_create:
json
{
"name": "browser_close",
"arguments": {
"sessionId": "vybp-a64d-2dqf-9vsq86"
}
}
Liberar a sessão prontamente mantém a contagem de sessões concorrentes da conta limpa e é o padrão certo no final de cada raspagem.
Escalando além do limite por consulta
O Google Maps limita uma única pesquisa a aproximadamente 120 lugares. Para consultas que excedem isso — "todos os restaurantes em Manhattan", "todos os dentistas na Califórnia" — a estratégia é uma grade geográfica:
- Divida a área de pesquisa em caixas delimitadoras menores. Um bairro, um código postal ou um quadrado de 2 km × 2 km normalmente retorna bem menos de 120 resultados, então cada ladrilho é totalmente esgotado.
- Realize uma consulta por ladrilho. Ou incorpore um segmento
@lat,lng,zoomna URL do Maps (ex:https://www.google.com/maps/search/coffee/@47.6097,-122.3331,15z) ou altere a string de consulta ("cafés em Pike Place" → "cafés em Belltown" → "cafés em Capitol Hill"). - Remova duplicados entre os mapas pelo
placeId. Um único local pode aparecer em mapas sobrepostos; oplaceIdanalisado a partir damapUrl(!1s0x<hex>:0x<hex>) é a chave de junção estável.
O mesmo padrão se compõe das primitivas do MCP — um browser_create + um browser_goto + rolagem + extração por mapa, com o agente mantendo o conjunto de remoção de duplicados entre os mapas na memória da conversa.
O Que Você Recebe de Volta
As ferramentas do MCP retornam texto bruto (HTML, texto da página, capturas de tela); a estrutura JSON é o que o agente monta. Para uma única passagem de pesquisa e rolagem com o modelo de descobrir → extrair acima, o esquema se parece com isto:
json
// O esquema reflete o que o agente emite quando solicitado a extrair cartões de local.
// Os valores dos campos são exemplos ilustrativos.
{
"query": "cafés em Pike Place Seattle",
"queryUrl": "https://www.google.com/maps/search/cafés+em+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": "Cafeteria",
"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
}
]
}
Algumas observações honestas sobre esta saída, que vale a pena saber antes de rodar em grande escala:
- Tempo de hidratação. O mapas SPA renderiza em ondas — canvas do mapa, depois shell do feed, depois cartões. Um
browser_wait_forcontraa.hfpxzcé o que controla a extração. Se o primeirobrowser_get_htmldo agente retornar apenas o shell, peça para ele esperar um pouco mais e re-extrair. - Estabilidade do seletor.
[role="article"],[role="feed"], stringsaria-labelem widgets de classificação, ea.hfpxzc[href]para omapUrlcanônico são os âncoras com a maior durabilidade. Nomes de classes (por exemplo,h1.DUwDvf,.jftiEf) funcionam hoje, mas podem mudar em novas versões; trate-os como um esforço de melhor prática e re-execute uma passagem de descoberta se um futuro scrape retornar vazio. - Colocação patrocinada. Cartões patrocinados se intercalam com resultados orgânicos e têm
[aria-label="Sponsored"]. O agente deve definirisSponsoredem vez de descartá-los, para que consumidores posteriores possam filtrar explicitamente. - Campos do painel de detalhes são condicionais. Telefone, site e horários vêm de linhas
button[data-item-id="…"]que não existem em todos os locais. Trate-os como anuláveis, em vez de obrigatórios. - Localidade e idioma. Texto da interface nos cartões de local (os rótulos dos botões
"horários","comentários","site") é traduzido para o idioma do país do proxy. Para consultas com destino aos EUA, os rótulos estão em inglês; para ES, FR, JP, as expressões regulares do parser precisam corresponder às strings localizadas ou o campo retorna nulo. - Limite por consulta. Aproximadamente 120 resultados por consulta no feed lateral. Para geografias maiores, use o padrão de mosaico de geolocalização acima e remova duplicados pelo
placeId.
FAQ
Q1: Preciso de um proxy para o Google Maps e posso escolher a região?
Cada sessão de navegador em nuvem passa automaticamente por um proxy residencial Scrapeless — nenhuma configuração de proxy separada é necessária para a chamada funcionar. No entanto, a região do proxy é definida no nível da conta e não é exposta como um argumento por chamada na ferramenta browser_create do MCP. Fluxos de trabalho que precisam de controle de região por consulta (resultados de Maps dos EUA vs ES vs JP) devem direcionar o navegador em nuvem através do scrapeless-scraping-browser CLI (que expõe --proxy-country), ou manter várias chaves de API Scrapeless configuradas para diferentes regiões padrão.
Q2: Qual é a diferença entre o modo stdio e o modo de streaming HTTP?
O modo stdio executa npx scrapeless-mcp-server como um processo filho do cliente MCP (Claude Desktop, Cursor, etc.) e é o padrão correto para agentes de desktop. O modo de streaming HTTP aponta o cliente para https://api.scrapeless.com/mcp e é o padrão correto para agentes hospedados em nuvem que não podem executar npx. Ambos os modos usam a mesma chave de API Scrapeless.
Q3: Como posso ultrapassar o limite de 120 resultados em uma consulta?
Divida a área de pesquisa em geografias menores (bairros, códigos postais, caixas delimitadoras de lat/lng) e execute uma consulta por mapa. Use o placeId analisado (da segmentação !1s0x<hex>:0x<hex> da mapUrl) para remover duplicados entre mapas sobrepostos. O padrão de geogrid é documentado na seção Escalando além do limite por consulta acima.
Q4: Posso extrair comentários de um local?
Sim. Depois que o feed for renderizado, clique no cartão para abrir o painel de detalhes, aguarde h1.DUwDvf, e então extraia os cartões de comentários da região .jftiEf — título, autor, classificação, corpo e data. A exploração é por local e aumenta o custo de solicitação; faça isso apenas quando o fluxo de trabalho precisar da carga de comentários.
Q5: O que acontece quando o Google Maps muda o DOM?
Executar novamente uma passagem de descoberta: peça ao agente para chamar browser_get_html na região relevante e reidentificar os âncoras estáveis atuais. [role="article"], [role="feed"], strings aria-label, e a.hfpxzc[href] são os que mais duram; nomes de classes rotacionam. O padrão de descoberta → extração da habilidade lida com isso sem mudanças de código.
Q6: Por que minha sessão às vezes retorna Acesso Negado ou uma página CAPTCHA?
Uma nova alocação de proxy ocasionalmente cai em um IP sinalizado. Peça ao agente para chamar browser_close e depois browser_create novamente para criar uma nova sessão. Alocações subsequentes têm sucesso.
Q9: Vários agentes podem compartilhar um servidor MCP?
Cada cliente ciente do MCP conecta-se à sua própria instância do servidor (em modo stdio) ou ao ponto de extremidade HTTP compartilhado (em modo transmitível). As sessões são isoladas pelo taskId retornado de browser_create, portanto, múltiplos agentes chamando o mesmo servidor MCP não compartilham cookies ou estado de rolagem. Para raspagens com alto volume, crie uma sessão por consulta em vez de reutilizar uma única sessão de longa duração.
Q10: Com quais clientes MCP isso funciona?
Qualquer cliente que suporte MCP. O protocolo é o contrato — a lista de ferramentas do servidor e a forma das chamadas são idênticas em todos os clientes. O Passo 2 inclui caminhos de configuração para Claude Desktop, Claude Code, Cursor, OpenAI Codex CLI, Gemini CLI e VS Code + GitHub Copilot Chat; o mesmo trecho JSON mcpServers pode ser usado em clientes personalizados em Python ou Node construídos contra o MCP TypeScript SDK, e o ponto de extremidade HTTP transmitível em https://api.scrapeless.com/mcp funciona com qualquer cliente HTTP.
Q11: O servidor MCP tem uma ferramenta dedicada do Google Maps?
Não — o servidor fornece primitivas genéricas de 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) além dos auxiliares em nível de página (scrape_html, scrape_markdown, scrape_screenshot) e ferramentas de dados do Google (google_search, google_trends). O agente compõe a raspagem do Maps a partir das primitivas do navegador; as mesmas primitivas são usadas para Amazon, Home Depot, Etsy e qualquer outro site pesado em JavaScript.
Q12: Por que o Maps carrega uma página de consentimento em vez de resultados de busca?
Quando a sessão do navegador na nuvem passa por um proxy residencial europeu, o Google interrompe a navegação com um intersticial de consent.google.com antes de mostrar o Maps. O agente deve chamar browser_get_text após browser_goto e, se a resposta contiver "consentimento" ou um rótulo de botão Aceitar (Aceitar tudo / Accetta tutto / Akzeptieren / Accepter), acionar browser_click contra o botão antes de tentar a navegação novamente. O Passo 2 cobre o trecho completo.
Q13: Por que minha sessão às vezes retorna um erro de conexão transitório como os error 10054 ou 503?
O pool de proxy residencial do Scrapeless ocasionalmente retorna um erro de alocação de curta duração em browser_create. Uma única nova tentativa geralmente tem sucesso — envolva browser_create em um loop de tentativa de 2 a 3 no código de produção, ou simplesmente peça ao agente para tentar novamente uma vez.
Q14: Quantos trabalhos de raspagem MCP posso executar simultaneamente?
Para confiabilidade, mantenha um cliente MCP para uma sessão em andamento por vez e encadeie chamadas dentro de uma única ação do agente. Para maior volume, execute vários clientes MCP (ou processos de trabalho atingindo o ponto de extremidade HTTP transmitível) e limite a concorrência a ≤ 3 sessões por host. Para trabalhos em lote de pura capacidade (10 mil+ consultas/hora), acione o scrapeless-scraping-browser CLI diretamente com um pool de trabalhadores paralelo; o caminho MCP é o melhor para descoberta guiada por agentes e cobertura geográfica baseada em tiles.
Q15: Posso executar isso sem um cliente MCP?
Sim. Dois caminhos: (1) chame o ponto de extremidade HTTP transmitível em https://api.scrapeless.com/mcp diretamente de qualquer cliente HTTP com o cabeçalho x-api-token; (2) acione o navegador na nuvem através do scrapeless-scraping-browser CLI via bash. O fluxo de trabalho orientado por MCP é o caminho recomendado para raspagem acionada por agentes; o CLI é o caminho certo para pipelines de lote escritas.
Q16: Por que usar uma URL canônica /maps/search/<query> em vez de acionar a caixa de busca?
A URL de busca de link profundo leva o agente diretamente a um SERP populado sem a necessidade de clicar na entrada de busca, digitar e pressionar Enter. Menos chamadas de ferramentas, menor chance de o agente clicar no controle errado, execução mais rápida de ponta a ponta. A mesma abordagem para URLs de locais: navegue diretamente para /maps/place/<slug>/data=!1s<placeId> em vez de acionar busca e clicar quando o placeId já é conhecido.
Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.



