Extraer datos de Google Maps con JavaScript: Guía completa
Google Maps contiene más de 5 millones de fichas comerciales. Cada ficha = dirección, teléfono, opiniones, horarios, fotos, sitio web. Es una mina de oro para la prospección, el estudio de mercado y el análisis competitivo.
Pero, ¿cómo extraer estos datos a gran escala? Existen tres enfoques: la API oficial de Google Maps, el web scraping personalizado en JavaScript o una herramienta dedicada. Este artículo cubre las tres — con sus costos reales, límites y cuándo usar cada una.
¿Por qué extraer datos de Google Maps?
Antes de entrar en la técnica, aclara tu necesidad. Los casos de uso no son los mismos.
Prospección comercial
Una agencia de limpieza quiere encontrar 500 restaurantes en un radio de 10 km. Exporta: nombre, dirección, teléfono, email. Realiza llamadas en frío dirigidas.
Necesidad: datos básicos (nombre, contacto), rapidez, volumen medio.
Análisis competitivo
Un restaurador analiza 50 restaurantes competidores: opiniones en Google, número de opiniones, horarios, precios (a través del sitio web), fotos, tecnologías utilizadas (¿usan Uber Eats? ¿Deliveroo? ¿Su propio sitio?).
Necesidad: datos enriquecidos (opiniones, stack tecnológico), contexto, volumen bajo a medio.
Estudio de mercado
Un franquiciador analiza más de 1,000 peluquerías en Francia para identificar las zonas desatendidas. Extrae: localización, calificación en Google, número de opiniones, horarios, ficha reclamada o no.
Necesidad: datos estructurados, filtrado avanzado, alto volumen, actualización mensual.
Detección de leads calificados
Una agencia de SEO busca restaurantes con calificación < 3 estrellas (clientes potenciales insatisfechos). Exporta aquellos con más de 50 opiniones (tamaño significativo) y sitio web sin Google Analytics.
Necesidad: opiniones en Google (texto + calificación + fecha), detección de tecnologías, filtros complejos, volumen medio.
Cada caso de uso implica un enfoque diferente. Veamos las opciones.
Opción 1: La API oficial de Google Maps JavaScript
Google ofrece una API JavaScript gratuita (con cuotas). Funciona en el navegador o en Node.js del lado del servidor.
Funcionalidades básicas
La API de Google Maps JavaScript permite 3 cosas principales:
- Geocodificación: convertir una dirección → coordenadas GPS
- Places API: buscar lugares (restaurantes, fontaneros, etc.) alrededor de una posición
- Detalles del lugar: recuperar la información detallada de un lugar (opiniones, horarios, fotos, URL, etc.)
Paso 1: Obtener una clave API
- Ve a Google Cloud Console
- Crea un proyecto
- Activa estas APIs: - Maps JavaScript API - Places API - Geocoding API
- Crea una clave API (tipo: clave de navegador o servidor según tu uso)
- Configura las restricciones (dominios permitidos, cuotas)
Importante: Google cobra más allá de las cuotas gratuitas. Por defecto: 25,000 llamadas/día gratuitas para Places, luego €0.017 por llamada.
Paso 2: Implementar la Geocodificación
Convertir una dirección en latitud/longitud.
const geocoder = new google.maps.Geocoder();
geocoder.geocode(
{ address: '75 Rue de Rivoli, Paris' },
(results, status) => {
if (status === 'OK') {
const lat = results[0].geometry.location.lat();
const lng = results[0].geometry.location.lng();
console.log(`Coordenadas: ${lat}, ${lng}`);
} else {
console.error(`Error: ${status}`);
}
}
);
Paso 3: Buscar lugares cercanos (Nearby Search)
Encontrar todos los restaurantes en un radio de 5 km alrededor de París.
const map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 48.8566, lng: 2.3522 }, // París
zoom: 15
});
const service = new google.maps.places.PlacesService(map);
const request = {
location: new google.maps.LatLng(48.8566, 2.3522),
radius: 5000, // 5 km
type: 'restaurant',
keyword: 'pizza' // Opcional: filtrar por palabra clave
};
service.nearbySearch(request, (results, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK) {
results.forEach(place => {
console.log(`${place.name} - ${place.vicinity}`);
});
}
});
Limitación importante: nearbySearch() devuelve máx 60 resultados por consulta, con paginación. Para obtener 500 restaurantes, debes hacer 9 consultas.
Paso 4: Recuperar los detalles completos (Place Details)
Cada lugar devuelto por nearbySearch() tiene un place_id. Úsalo para obtener los detalles completos.
const request = {
placeId: 'ChIJIQBpAG2ahYAR_6128GltTXQ', // Ejemplo: Torre Eiffel
fields: [
'name',
'formatted_address',
'formatted_phone_number',
'website',
'opening_hours',
'reviews',
'rating',
'user_ratings_total',
'photos'
]
};
service.getDetails(request, (place, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK) {
console.log(`Nombre: ${place.name}`);
console.log(`Dirección: ${place.formatted_address}`);
console.log(`Teléfono: ${place.formatted_phone_number}`);
console.log(`Sitio web: ${place.website}`);
console.log(`Calificación: ${place.rating} (${place.user_ratings_total} opiniones)`);
console.log(`Horarios:`, place.opening_hours.weekday_text);
// Opiniones en Google
place.reviews.forEach(review => {
console.log(`${review.author_name}: ${review.rating}/5 - "${review.text}"`);
});
}
});
Costos reales de la API de Google Maps
| Operación | Cuota gratuita | Precio más allá |
|---|---|---|
| Geocodificación | 25,000/día | €0.005 por llamada |
| Nearby Search | 25,000/día | €0.032 por llamada |
| Place Details | 25,000/día | €0.017 por llamada |
| Búsqueda de texto | 25,000/día | €0.032 por llamada |
Ejemplo real: extraer 1,000 restaurantes con detalles completos.
- 1,000 Nearby Search = 17 llamadas (máx 60 resultados/llamada) = €0.54
- 1,000 Place Details = €17
Total: ~€17.50 por 1,000 restaurantes.
Parece poco, pero: - Debes hacerlo cada mes para las actualizaciones - Estás limitado a 60 resultados por consulta (difícil de paginar) - Las opiniones en Google devueltas son limitadas (máx 5 por lugar) - No obtienes las tecnologías detectadas (WordPress, Shopify, etc.)
Límites de la API de Google Maps JavaScript
| Limitación | Impacto |
|---|---|
| Máx 60 resultados por consulta | Paginación manual compleja |
| Máx 5 opiniones por lugar | No hay análisis completo de opiniones |
| No hay filtrado por calificación en Google | Recuperas todos los resultados |
| No hay filtrado por número de opiniones | No hay enfoque en las fichas "maduras" |
| No hay detección de tecnologías | No sabes si el sitio usa WordPress, Shopify, etc. |
| No hay datos SIRET (Francia) | No hay enriquecimiento jurídico/financiero |
| Cuotas limitadas | Costos que aumentan rápidamente a gran escala |
Opción 2: Web scraping personalizado en JavaScript con Puppeteer
Si deseas eludir los límites de la API oficial, puedes hacer scraping directamente del sitio de Google Maps con Puppeteer (una biblioteca de Node.js que automatiza un navegador Chrome).
¿Por qué Puppeteer?
Puppeteer lanza un navegador Chrome automatizado, va a Google Maps, simula clics/desplazamientos y extrae el HTML. Así puedes recuperar más de 60 resultados, las opiniones completas, las fotos, etc.
Instalación
npm install puppeteer
Ejemplo: Scraper los restaurantes de París
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Ir a Google Maps
await page.goto('https://www.google.com/maps/search/restaurants+paris', {
waitUntil: 'networkidle2'
});
// Esperar a que se carguen los resultados
await page.waitForSelector('[role="listitem"]');
// Desplazar para cargar más resultados
const resultsContainer = await page.$('[role="main"]');
for (let i = 0; i < 5; i++) {
await resultsContainer.evaluate(el => {
el.scrollTop = el.scrollHeight;
});
await page.waitForTimeout(1000); // Esperar a que se cargue
}
// Extraer los datos
const restaurants = await page.evaluate(() => {
const items = document.querySelectorAll('[role="listitem"]');
return Array.from(items).map(item => {
const nameEl = item.querySelector('[role="heading"]');
const ratingEl = item.querySelector('[aria-label*="estrella"]');
const addressEl = item.querySelector('[data-item-id*="address"]');
return {
name: nameEl ? nameEl.textContent : 'N/A',
rating: ratingEl ? ratingEl.getAttribute('aria-label') : 'N/A',
address: addressEl ? addressEl.textContent : 'N/A'
};
});
});
console.log(restaurants);
await browser.close();
})();
Problemas con este enfoque
-
Google bloquea rápidamente: Después de 10-20 consultas, Google detecta el scraping y te pide que confirmes que no eres un robot (CAPTCHA).
-
Mantenimiento constante: Google cambia su HTML regularmente. Tu código se rompe cada 2-3 meses.
-
Lento: Puppeteer debe lanzar un navegador completo para cada búsqueda. Hacer scraping de 10,000 restaurantes = 10,000 navegadores lanzados = horas de ejecución.
-
Costoso en recursos: Cada navegador consume 100-200 MB de RAM. Hacer scraping en paralelo = servidor potente requerido.
-
En contra de los términos de uso: Google prohíbe explícitamente el scraping de Maps.
Veredicto: Puppeteer funciona para pruebas puntuales (50-100 resultados), no para una extracción a gran escala.
Opción 3: Utilizar una herramienta dedicada (sin código)
Esta es la solución más pragmática para el 95% de los casos de uso. En lugar de codificar, utilizas una herramienta que:
- Gestiona la extracción a gran escala
- Elude los bloqueos de Google
- Devuelve los datos estructurados (CSV, JSON, API)
- Incluye las opiniones completas de Google
- Detecta las tecnologías utilizadas
- Actualiza los datos mensualmente
¿Por qué una herramienta dedicada?
| Criterio | API de Google | Puppeteer | Herramienta dedicada |
|---|---|---|---|
| Costo por 10,000 resultados | €170+ | Gratis (pero lento) | €44-99/mes |
| Tiempo para 10,000 resultados | 2-3 días (cuotas) | 4-6 horas | 5 minutos |
| Opiniones completas de Google | Máx 5 por lugar | Sí | Sí |
| Filtrado por calificación en Google | No | No | Sí |
| Detección de tecnologías | No | No | Sí |
| Mantenimiento | Alto (cambios en la API) | Alto (cambios en HTML) | Cero |
| Bloqueo de Google | Raro | Frecuente | Nunca |
Casos de uso prácticos con JavaScript
A continuación, 3 escenarios reales y cómo implementarlos.
Caso 1: Buscar 50 fontaneros en Lyon con la API de Google Maps
Necesidad: nombre, dirección, teléfono, sitio web, calificación. Volumen bajo. Presupuesto limitado.
Solución: API oficial de Google Maps.
async function findPlumbers(city, limit = 50) {
const geocoder = new google.maps.Geocoder();
// Geocodificar la ciudad
const cityCoords = await new Promise((resolve) => {
geocoder.geocode({ address: city }, (results) => {
resolve(results[0].geometry.location);
});
});
const map = new google.maps.Map(document.getElementById('map'), {
center: cityCoords,
zoom: 12
});
const service = new google.maps.places.PlacesService(map);
const allResults = [];
// Hacer múltiples consultas (máx 60 por consulta)
for (let i = 0; i < Math.ceil(limit / 60); i++) {
const results = await new Promise((resolve) => {
service.nearbySearch(
{
location: cityCoords,
radius: 15000,
type: 'plumber',
pageToken: i === 0 ? null : nextPageToken
},
(results, status, pagination) => {
nextPageToken = pagination.nextPage ? pagination.nextPageToken : null;
resolve(results || []);
}
);
});
allResults.push(...results);
if (allResults.length >= limit) break;
}
// Recuperar los detalles para cada resultado
const details = await Promise.all(
allResults.slice(0, limit).map(place => {
return new Promise((resolve) => {
service.getDetails(
{
placeId: place.place_id,
fields: ['name', 'formatted_address', 'formatted_phone_number', 'website', 'rating']
},
(place) => resolve(place)
);
});
})
);
return details.map(p => ({
name: p.name,
address: p.formatted_address,
phone: p.formatted_phone_number,
website: p.website,
rating: p.rating
}));
}
// Uso
findPlumbers('Lyon').then(plumbers => {
console.table(plumbers);
// Exportar a CSV
downloadCSV(plumbers);
});
Costo: ~€0.50 (17 consultas Nearby + 50 Place Details)
Tiempo: 30 segundos
Limitación: No sabes cuáles están reclamadas, cuántas opiniones tienen, o si utilizan un sitio personalizado/Wix/Squarespace.
Caso 2: Analizar 200 restaurantes competidores (opiniones, tecnologías)
Necesidad: opiniones completas, calificación, número de opiniones, tecnologías utilizadas. Volumen medio. Presupuesto medio.
Solución: Herramienta dedicada (la API de Google Maps solo da un máximo de 5 opiniones).
Con una herramienta, exportas en 5 minutos:
Nombre,Dirección,Calificación,Número de opiniones,Opiniones (texto),Opiniones (fecha),Opiniones (autor),Sitio web,Tecnologías detectadas
Le Jules Verne,5 Rue Eiffel,4.8,1250,"Excelente relación calidad/precio",2024-01-15,Pierre M.,lejulesverne.fr,"WordPress, WooCommerce, Google Analytics"
Septime,80 Rue Charonne,4.7,890,"Servicio impecable",2024-01-14,Marie D.,septimeparis.com,"Personalizado, Shopify"
Entonces puedes: - Identificar los restaurantes bien calificados (4.5+) con más de 500 opiniones (tamaño significativo) - Leer las opiniones negativas para identificar los puntos débiles de los competidores - Ver qué restaurantes utilizan Shopify (venden en línea) vs WordPress (sitio personalizado)
Caso 3: Prospección ABM — Encontrar 500 restaurantes con sitio sin Google Analytics
Necesidad: restaurantes de tamaño medio (50-200 opiniones), calificación 3.5+, sitio web sin Google Analytics (lead potencial para agencia de SEO/analytics).
Solución: Herramienta dedicada con filtros avanzados y detección de tecnologías.
```javascript // Pseudo-código (la API de Google Maps no puede hacer esto) const restaurants = await tool.search({ location: 'Francia', category: 'restaurant', minRating: 3.5, minReviews: 50, maxReviews: 200, hasWebsite: true, missingTechnology: 'Google Analytics' // EXCLUSIVO });
// Resultado: 500 restaurantes calificados // Los contactas con: "Hemos visto que su sitio no tiene"
¿Listo para empezar?
Accede a todas las empresas de Google Maps, enriquecidas con emails y datos legales.
Prueba IBLead gratisArtículos relacionados
10 Consejos Comprobados para Conseguir que los Clientes Dejen Más Reseñas en Google Maps
Descubre 10 estrategias prácticas para aumentar las reseñas en Google Maps.
7 Errores de Cold Email a Evitar: Ejemplos y Plantillas
Evita estos 7 errores de cold email para mejorar tus tasas de respuesta. Ejemplos reales, plantillas AIDA y soluciones comprobadas.
Datos de Google Maps para ABM: La Guía Estratégica Completa
Descubre cómo los datos de marketing basado en cuentas de Google Maps generan un 208% más de ingresos.