This project is currently in alpha and under active development.
A powerful Node.js CLI tool and JavaScript library for scraping Google Maps business listings using Puppeteer — with automatic JSON + Excel (XLSX) export. Built and maintained by Code Media Labs.
- Features
- Prerequisites
- Installation
- CLI Usage
- Library Usage (Node.js)
- Examples
- Troubleshooting
- Development
- Contributing
- License
-
🔍 Scrapes Google Maps business listings for any search query
-
📊 Extracts detailed business data:
- Name
- Star rating
- Total reviews
- Phone number
- Google Maps URL
-
🔁 Automatically scrolls until no new results are found
-
🛡️ Deduplicates entries by Maps URL
-
📦 Multiple output formats:
results.jsonresults.xlsx(ExcelJS)
-
🧰 Flexible usage:
- CLI tool
- Importable NPM library
-
⚡ Configurable scroll limits and headless mode
-
🎯 Great for lead generation, market research, competitor analysis
- Node.js ≥ 18
- npm or yarn
Check versions:
node --version
npm --versionInstall Chromium dependencies:
sudo apt-get update
sudo apt-get install -y \
ca-certificates fonts-liberation libappindicator3-1 libasound2 \
libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 \
libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 \
libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 \
libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \
lsb-release wget xdg-utils`Check missing libraries:
ldd $(which chromium-browser) | grep not
Puppeteer automatically downloads a compatible Chromium build (≈ 170–280MB).
No configuration required for most users.
npm install -g @cml/google-maps-scraper
Check version:
gmaps-scraper --version
npm install @cml/google-maps-scraper
gmaps-scraper scrape -q "<your search query>"`gmaps-scraper scrape -q "Interior Designers in Bhubaneswar"| Flag | Description | Default | Required |
|---|---|---|---|
-q, --query |
Google Maps search query | — | ✅ Yes |
-o, --output |
Output JSON file path | results.json |
No |
-m, --max-scrolls |
Maximum scroll attempts | 100 |
No |
--headless |
Run Puppeteer in headless mode | false |
No |
Save to a custom file:
gmaps-scraper scrape -q "Restaurants in Cuttack" -o ./data/restaurants.jsonHeadless + limited scrolls:
gmaps-scraper scrape -q "Hotels in Puri" --headless -m 50import { scrapeGoogleMaps } from "@cml/google-maps-scraper";
const results = await scrapeGoogleMaps({
searchQuery: "Cafes in Cuttack",
outputPath: "cafes.json",
maxScrollAttempts: 80,
headless: true,
});
console.log(`Found ${results.length} cafes`);
console.log(results);import { scrapeGoogleMaps } from "@cml/google-maps-scraper";
interface Business {
name: string;
rating: string;
reviews_count: string;
phone: string;
maps_link: string;
}
async function findBusinesses(query: string): Promise<Business[]> {
return scrapeGoogleMaps({
searchQuery: query,
outputPath: `${query.replace(/\s+/g, "_")}.json`,
maxScrollAttempts: 100,
headless: true,
});
}
const businesses = await findBusinesses("Gyms in Bhubaneswar");
console.log(businesses);| Parameter | Type | Description | Default | Required |
|---|---|---|---|---|
searchQuery |
string |
Google Maps search term | — | ✅ Yes |
outputPath |
string |
Output JSON file path | "results.json" |
No |
maxScrollAttempts |
number |
Maximum scroll attempts | 100 |
No |
headless |
boolean |
Run Puppeteer in headless mode | false |
No |
gmaps-scraper scrape -q "Hair Salons in Bhubaneswar" -o salons.json -m 150gmaps-scraper scrape -q "Manufacturing Companies in Cuttack" --headlessimport { scrapeGoogleMaps } from "@cml/google-maps-scraper";
import fs from "fs/promises";
const queries = [
"Bakeries in Puri",
"Bookstores in Bhubaneswar",
"Electronics Shops in Cuttack",
];
async function scrapeMultiple() {
const allResults = [];
for (const query of queries) {
console.log(`Scraping: ${query}`);
const results = await scrapeGoogleMaps({
searchQuery: query,
outputPath: `${query.replace(/\s+/g, "_")}.json`,
maxScrollAttempts: 50,
headless: true,
});
allResults.push({ query, count: results.length, businesses: results });
}
await fs.writeFile(
"combined_results.json",
JSON.stringify(allResults, null, 2)
);
console.log("✅ All queries completed!");
}
scrapeMultiple();npm install --save-dev typescriptInstall dependencies from the Prerequisites section.
- Check internet
- Check search query
- Increase
maxScrollAttempts - Disable headless mode
- Reduce scroll limit
- Ensure 2GB+ free RAM
- Close other apps
sudo npm install -g @cml/google-maps-scrapergit clone https://github.com/Code-Media-Labs/google-maps-scraper.git cd google-maps-scraper
npm install
node ./bin/gmaps-scraper.js scrape -q "Hotels in Puri"
npm run build
npm test
google-maps-scraper/ ├── bin/ │ └── gmaps-scraper.js ├── src/ │ ├── scraper.js │ ├── excelConverter.js │ └── index.js ├── tests/ │ └── scraper.test.js │ └── excelConverter.test.js ├── package.json ├── vitest.config.js └── README.md
- Fork the repo
- Create a branch:
git checkout -b feature/amazing-feature
- Commit:
git commit -m "feat: add amazing feature"
- Push:
git push origin feature/amazing-feature
- Open a Pull Request
feat:new featurefix:bug fixdocs:documentationrefactor:internal codetest:testschore:maintenance
MIT © Code Media Labs
If you find this tool helpful:
- ⭐ Star the repo
- 🐛 Report issues
- 💡 Suggest features
- 🤝 Contribute