Skip to content

Commit ac93667

Browse files
committed
gmapsscraper Python SDK v0.1.0 — zero-dependency client for the gmapsscraper.io API
0 parents  commit ac93667

9 files changed

Lines changed: 627 additions & 0 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
strategy:
12+
matrix:
13+
python: ['3.9', '3.11', '3.13']
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: actions/setup-python@v5
17+
with:
18+
python-version: ${{ matrix.python }}
19+
- run: python -m unittest discover -s tests -v

‎.gitignore‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
__pycache__/
2+
*.pyc
3+
dist/
4+
build/
5+
*.egg-info/
6+
.venv/
7+
.DS_Store

‎LICENSE‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 gmapsscraper.io
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

‎README.md‎

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# gmapsscraper
2+
3+
[![PyPI version](https://img.shields.io/pypi/v/gmapsscraper.svg)](https://pypi.org/project/gmapsscraper/)
4+
[![Python versions](https://img.shields.io/pypi/pyversions/gmapsscraper.svg)](https://pypi.org/project/gmapsscraper/)
5+
[![license](https://img.shields.io/pypi/l/gmapsscraper.svg)](./LICENSE)
6+
7+
Official Python SDK for the [gmapsscraper.io](https://gmapsscraper.io) API — a **Google Maps scraper** for lead generation. Extract business names, addresses, phone numbers, **emails**, websites, ratings, review counts, categories and coordinates from Google Maps in a few lines of Python.
8+
9+
- 🪶 **Zero dependencies** — pure standard library (`urllib` + `csv`)
10+
- 🐍 **Python 3.9+**, fully type-hinted (`py.typed`)
11+
- 📧 **Email extraction** — crawls business websites for contact emails
12+
- 🗺️ **Auto-geocoding** — just write `"dentist in Chicago IL"`, no coordinates needed
13+
14+
## Install
15+
16+
```bash
17+
pip install gmapsscraper
18+
```
19+
20+
Get a free API key (10 credits = 5 searches, no credit card) at **[gmapsscraper.io/dashboard](https://gmapsscraper.io/dashboard)**.
21+
22+
## Quick start
23+
24+
```python
25+
from gmapsscraper import GMapsScraper
26+
27+
client = GMapsScraper("YOUR_API_KEY")
28+
29+
# One call: submit → poll → download parsed results
30+
leads = client.scrape("coffee shop in Austin TX", email=True)
31+
32+
print(len(leads), "businesses found")
33+
print(leads[0])
34+
# {
35+
# "title": "Houndstooth Coffee",
36+
# "address": "401 Congress Ave ...",
37+
# "phone": "+1 512-...",
38+
# "email": "hello@...",
39+
# "website": "https://...",
40+
# "rating": "4.7",
41+
# "reviews_count": "1912",
42+
# "category": "Coffee shop",
43+
# "latitude": "30.2672", "longitude": "-97.7431",
44+
# "google_maps_url": "https://www.google.com/maps/place/...",
45+
# "opening_hours": "..."
46+
# }
47+
```
48+
49+
## Step-by-step API
50+
51+
If you want control over each stage (e.g. queue jobs and collect later):
52+
53+
```python
54+
# 1. Submit a job (costs 2 credits, multiple keywords = same cost)
55+
job = client.create_job(
56+
["plumber in Miami FL", "plumbing service in Miami FL"],
57+
email=True, depth=2,
58+
)
59+
60+
# 2. Wait for completion (polls every 10s)
61+
client.wait_for_job(job["id"], on_progress=lambda j: print("status:", j["status"]))
62+
63+
# 3a. Parsed dicts…
64+
records = client.download_records(job["id"])
65+
66+
# 3b. …or the raw CSV
67+
csv_text = client.download_csv(job["id"])
68+
69+
# Check your balance
70+
balance = client.credits() # {"credits": 8}
71+
```
72+
73+
## Options
74+
75+
All options for `scrape()` / `create_job()` (names match the REST API wire format and are stable):
76+
77+
| Option | Type | Default | Description |
78+
| ----------- | -------------- | ------- | ---------------------------------------------------- |
79+
| `email` | bool | `False` | Extract business emails from websites |
80+
| `depth` | int (1–2) | `2` | Higher = more results, **same credit cost** |
81+
| `zoom` | int (1–21) | `15` | Map zoom level |
82+
| `radius` | int (meters) | `20000` | Search radius |
83+
| `lang` | str | `"en"` | ISO 639-1 result language |
84+
| `fast_mode` | bool | `True` | Skip deep website crawling |
85+
| `max_time` | int (s) | `3600` | Job timeout on the backend |
86+
| `lat`/`lon` | str \| float | — | Coordinates (auto-geocoded from keywords if omitted) |
87+
88+
`scrape()` and `wait_for_job()` also accept `poll_interval` (seconds, default `10` — the API minimum; keep it there to avoid rate limits), `timeout` (seconds, default `3600`) and `on_progress(job)`.
89+
90+
## Error handling
91+
92+
All failures — HTTP errors, network failures, failed jobs and timeouts — raise `GMapsScraperError` with `status` and `body`. Invalid arguments raise `TypeError`:
93+
94+
```python
95+
from gmapsscraper import GMapsScraper, GMapsScraperError
96+
97+
try:
98+
client.scrape("dentist in Chicago IL")
99+
except GMapsScraperError as err:
100+
# 401 invalid key · 402 out of credits · 422 bad params · 429 rate limited
101+
print(err.status, err)
102+
```
103+
104+
| Status | Meaning |
105+
| ------ | -------------------------------------------------------------------------- |
106+
| 401 | Invalid API key |
107+
| 402 | Insufficient credits — top up at [gmapsscraper.io](https://gmapsscraper.io/#pricing) |
108+
| 422 | Invalid parameters |
109+
| 429 | Rate limited (1000 req/day) or too many concurrent jobs (max 10) |
110+
| 502 | Backend temporarily unavailable |
111+
112+
## Tips for better results
113+
114+
- Be specific: `"vegan restaurant in Brooklyn NY"` beats `"restaurant in New York"`.
115+
- Pass several related keywords in one job — broader coverage, same 2 credits.
116+
- Set `email=True` whenever you need contact info for cold outreach.
117+
- Jobs typically finish in 30–120 seconds.
118+
119+
## Related resources
120+
121+
- 📘 [API documentation](https://gmapsscraper.io/llms.txt) (also great as LLM context)
122+
- 📦 [Node.js SDK](https://github.com/gmapsscraper/gmapsscraper-js) — `npm install @gmapsscraper/sdk`
123+
- 🤖 [Claude / AI agent skills](https://github.com/gmapsscraper/google-maps-agent-skills) — use gmapsscraper from Claude Code and other agents
124+
- 🧩 [Chrome extension](https://github.com/gmapsscraper/google-maps-scraper) — scrape Google Maps without code
125+
- ✍️ [Blog: Google Maps scraping guides](https://gmapsscraper.io/blog)
126+
127+
## License
128+
129+
[MIT](./LICENSE) © [gmapsscraper.io](https://gmapsscraper.io)

‎examples/basic.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Usage: GMAPSSCRAPER_API_KEY=your_key python examples/basic.py
2+
# Get a free key (10 credits): https://gmapsscraper.io/dashboard
3+
import os
4+
5+
from gmapsscraper import GMapsScraper
6+
7+
client = GMapsScraper(os.environ["GMAPSSCRAPER_API_KEY"])
8+
9+
print("Credits remaining:", client.credits()["credits"])
10+
11+
leads = client.scrape(
12+
"coffee shop in Austin TX",
13+
email=True,
14+
on_progress=lambda job: print(f"Job {job['id']}: {job['status']}"),
15+
)
16+
17+
print(f"Found {len(leads)} businesses")
18+
for lead in leads[:5]:
19+
print(f"- {lead['title']} | {lead['phone']} | {lead['email']} | {lead['website']}")

‎pyproject.toml‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "gmapsscraper"
7+
version = "0.1.0"
8+
description = "Official Python SDK for the gmapsscraper.io API — scrape Google Maps business data: names, emails, phones, websites, ratings, reviews."
9+
readme = "README.md"
10+
license = { text = "MIT" }
11+
requires-python = ">=3.9"
12+
authors = [{ name = "gmapsscraper.io" }]
13+
keywords = [
14+
"google maps scraper",
15+
"google maps",
16+
"scraper",
17+
"lead generation",
18+
"leads",
19+
"email extractor",
20+
"local business",
21+
"business data",
22+
"b2b",
23+
"places",
24+
"reviews",
25+
"sdk",
26+
"api client",
27+
]
28+
classifiers = [
29+
"Development Status :: 4 - Beta",
30+
"Intended Audience :: Developers",
31+
"License :: OSI Approved :: MIT License",
32+
"Operating System :: OS Independent",
33+
"Programming Language :: Python :: 3",
34+
"Programming Language :: Python :: 3.9",
35+
"Programming Language :: Python :: 3.10",
36+
"Programming Language :: Python :: 3.11",
37+
"Programming Language :: Python :: 3.12",
38+
"Programming Language :: Python :: 3.13",
39+
"Topic :: Internet :: WWW/HTTP",
40+
"Topic :: Software Development :: Libraries :: Python Modules",
41+
"Typing :: Typed",
42+
]
43+
44+
[project.urls]
45+
Homepage = "https://gmapsscraper.io"
46+
Repository = "https://github.com/gmapsscraper/gmapsscraper-python"
47+
Documentation = "https://gmapsscraper.io/llms.txt"
48+
Issues = "https://github.com/gmapsscraper/gmapsscraper-python/issues"
49+
50+
[tool.hatch.build.targets.wheel]
51+
packages = ["src/gmapsscraper"]

0 commit comments

Comments
 (0)