Overview
Deeger Search provides two APIs: SERP Search (Google, Startpage, Yahoo) and Google Maps Scraping (business data extraction with 30+ fields). All requests go through residential proxies with real browser TLS fingerprints.
Both APIs use the same async job model: submit a request, receive ajob_id, poll for results. SERP searches complete in 2-8 seconds, Maps scraping in 5-60 seconds depending on area size.
https://api.search.deeger.ioAuthentication
All API requests require an API key passed via the X-API-Key header.
curl https://api.search.deeger.io/v1/health \
-H "X-API-Key: sk-your-api-key"API keys are created from the dashboard after registration. Each key is tied to a plan that determines monthly search limits and concurrent request capacity.
| Plan | SERP searches/mo | Maps results/mo | Concurrent |
|---|---|---|---|
Free | 200 | 50 | 2 |
Starter | 5,000 | 500 | 5 |
Growth | 30,000 | 2,500 | 10 |
Pro | 100,000 | 10,000 | 25 |
Business | 500,000 | 25,000 | 50 |
Enterprise | 2,000,000 | 50,000 | 100 |
Submit a Search
https://api.search.deeger.io/v1/searchEnqueue a search job. Returns a job_id that you use to poll for results.
Request body
| Parameter | Type | Description | Default |
|---|---|---|---|
queryrequired | string | Search query (1-500 chars) | — |
engine | string | Search engine. Default: "google" | "google" |
pages | integer | Number of result pages (1-10) | 1 |
gl | string | Country code ISO 3166-1 alpha-2 | "pe" |
hl | string | Language code BCP-47 | "es" |
location | string | City/region targeting (e.g. "Lima, Peru") | null |
proxy_provider | string | Proxy provider: auto | rayobyte | plainproxies | geonode | "auto" |
curl -X POST https://api.search.deeger.io/v1/search \
-H "X-API-Key: sk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"query": "best restaurants in Lima",
"engine": "google",
"gl": "pe",
"hl": "es",
"pages": 1
}'{
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "pending",
"message": "Search enqueued. Check status at GET /v1/search/{job_id}"
}Get Results
https://api.search.deeger.io/v1/search/{job_id}Poll this endpoint until status is "done" or "error". Results are available for 1 hour after completion.
Status values
| Status | Description |
|---|---|
pending | Job is queued, not yet picked up by a worker |
processing | Worker is executing the search |
done | Search completed, results available |
error | Search failed (see error field) |
{
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "done",
"query": "best restaurants in Lima",
"engine": "google",
"created_at": 1709856000.0,
"completed_at": 1709856004.2,
"search_information": {
"total_results": "About 45,200,000 results",
"time_taken": "0.52s"
},
"organic_results": [
{
"position": 1,
"title": "Los 10 mejores restaurantes de Lima - TripAdvisor",
"url": "https://tripadvisor.com/Restaurants-Lima.html",
"snippet": "Descubre los mejores restaurantes en Lima, Peru...",
"displayed_url": "tripadvisor.com > Lima"
},
{
"position": 2,
"title": "Central Restaurante - Lima",
"url": "https://centralrestaurante.com.pe",
"snippet": "Mejor restaurante de Sudamerica 2023...",
"displayed_url": "centralrestaurante.com.pe"
}
],
"related_questions": [
"What is the best restaurant in Lima?",
"Is Lima known for food?"
],
"related_searches": [
"best ceviche in Lima",
"fine dining Lima Peru"
],
"knowledge_graph": null,
"result_count": 10
}Polling example (Python)
import requests, time
API_KEY = "sk-your-api-key"
BASE = "https://api.search.deeger.io"
# 1. Submit search
resp = requests.post(f"{BASE}/v1/search", json={
"query": "Irish breakfast Dublin",
"engine": "google",
"gl": "us",
"hl": "en",
}, headers={"X-API-Key": API_KEY})
job_id = resp.json()["job_id"]
# 2. Poll for results
while True:
resp = requests.get(
f"{BASE}/v1/search/{job_id}",
headers={"X-API-Key": API_KEY}
)
data = resp.json()
if data["status"] == "done":
for r in data["organic_results"]:
print(f'{r["position"]}. {r["title"]}')
print(f' {r["url"]}')
break
elif data["status"] == "error":
print(f'Error: {data.get("error")}')
break
time.sleep(2)Maps: Submit Search
https://api.search.deeger.io/v1/mapsScrape Google Maps for businesses in a geographic area. Uses grid-based search with Nominatim geocoding and Shapely polygon boundaries for precise coverage.
Request body
| Parameter | Type | Description | Default |
|---|---|---|---|
queryrequired | string | Location to search (e.g. "Miraflores, Lima") | — |
search_terms | string | Comma-separated business types (e.g. "Hotels,Restaurants") | all types |
max_results | integer | Maximum businesses to return (1-1000) | 100 |
curl -X POST https://api.search.deeger.io/v1/maps \
-H "X-API-Key: sk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"query": "Miraflores, Lima",
"search_terms": "Hotels,Restaurants",
"max_results": 50
}'{
"job_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"status": "pending",
"message": "Maps search enqueued. Check status at GET /v1/maps/{job_id}"
}Maps jobs take longer than SERP searches (5-60 seconds) because they search multiple grid cells across the geographic area. Use a polling interval of 3-5 seconds.
Maps: Get Results
https://api.search.deeger.io/v1/maps/{job_id}Poll until status is "done". Returns an array of businesses with 30+ fields each.
{
"job_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"status": "done",
"query": "Miraflores, Lima",
"result_count": 50,
"elapsed_seconds": 8.3,
"results": [
{
"place_id": "0x9105c81f...",
"business_name": "Maido",
"business_type": "Peruvian restaurant, Fine dining",
"description": "Modern eatery with Japanese fusion food",
"about": "Award-winning Nikkei cuisine...",
"address": "Ca. San Martín 399, Miraflores",
"full_address": "Maido, Ca. San Martín 399, Miraflores 15074, Peru",
"city": "Miraflores, Lima",
"area": "Miraflores, Peru",
"country_code": "PE",
"latitude": -12.1254,
"longitude": -77.0306,
"stars": 4.7,
"phone": "+51 1 3135100",
"website": "https://maido.pe/",
"facebook": null,
"menu_url": "https://maido.mesa247.pe/reservas/maido",
"opening_hours": {"Friday": "1-10 pm"},
"timezone": "America/Lima",
"amenities": {"Accessibility": {"Wheelchair-accessible entrance": true}},
"highlights": null,
"hotel_class": null,
"check_in": null,
"check_out": null,
"owner": "Maido (Owner)",
"plus_code": "VXF9+RQ Miraflores",
"maps_url": "https://google.com/maps/place/Maido/data=...",
"photo_url": "https://lh5.googleusercontent.com/..."
}
]
}Polling example (Python)
import requests, time
API_KEY = "sk-your-api-key"
BASE = "https://api.search.deeger.io"
# 1. Submit maps search
resp = requests.post(f"{BASE}/v1/maps", json={
"query": "Bogota, Colombia",
"search_terms": "Hotels",
"max_results": 20,
}, headers={"X-API-Key": API_KEY})
job_id = resp.json()["job_id"]
# 2. Poll for results (maps takes longer)
while True:
resp = requests.get(
f"{BASE}/v1/maps/{job_id}",
headers={"X-API-Key": API_KEY}
)
data = resp.json()
if data["status"] == "done":
for biz in data["results"]:
print(f'{biz["business_name"]} - {biz["stars"]}★')
print(f' {biz["phone"]} | {biz["address"]}')
if biz["hotel_class"]:
print(f' {biz["hotel_class"]}')
break
elif data["status"] == "error":
print(f'Error: {data.get("error")}')
break
time.sleep(3)Maps: Response Fields
Each business in the results array contains the following fields. Fields are null when not available for that business type.
| Field | Type | Description |
|---|---|---|
place_id | string | Google Maps internal place ID |
business_name | string | Business name |
business_type | string | Category (e.g. "Restaurant, Peruvian restaurant") |
description | string | Short description (e.g. "Luxe hotel offering dining & a pool") |
about | string | Editorial description from Google |
address | string | Street address |
full_address | string | Complete formatted address with city/country |
city | string | Search query location |
area | string | Neighborhood/district (e.g. "Miraflores, Peru") |
country_code | string | ISO country code (e.g. "PE") |
latitude | number | Latitude coordinate |
longitude | number | Longitude coordinate |
stars | number | Rating (1.0-5.0) |
phone | string | Phone with country code |
website | string | Website URL(s) |
facebook | string | Facebook page URL |
menu_url | string | Reservation/menu link (OpenTable, etc.) |
opening_hours | object | Hours by day (e.g. {"Friday": "6 am-11 pm"}) |
timezone | string | IANA timezone (e.g. "America/Lima") |
amenities | object | Grouped attributes (Accessibility, Services, etc.) |
highlights | array | Quick features (e.g. ["Free Wi-Fi", "Free breakfast"]) |
hotel_class | string | Hotel star rating (e.g. "5-star hotel") |
check_in | string | Check-in time (e.g. "15:00") |
check_out | string | Check-out time (e.g. "12:00") |
owner | string | Business owner name |
plus_code | string | Google Plus Code |
maps_url | string | Google Maps URL |
photo_url | string | Business photo/logo URL |
hotel_class, check_in, check_out, highlights) are only populated for hotels and lodging. Restaurant-specific fields like menu_url are only populated when available.Check Usage
https://api.search.deeger.io/v1/usageReturns your current monthly usage and remaining quota.
{
"client": "my-app",
"plan": "starter",
"monthly_limit": 5000,
"usage_this_month": 1234,
"remaining_this_month": 3766,
"maps_monthly_limit": 500,
"maps_usage_this_month": 42,
"maps_remaining_this_month": 458
}Search Engines
Use the engine parameter to choose which search engines to query.
| Value | Description |
|---|---|
google | Google Search (default). Most comprehensive results. |
startpage | Startpage (Google proxy). No CAPTCHAs needed. |
yahoo | Yahoo Search. Alternative result set. |
both | Google + Startpage in parallel. |
all | Google + Startpage + Yahoo in parallel. |
When using both or all, results from each engine are returned under separate keys in the response.
Geo Targeting
Control where your search appears to originate using the gl, hl, and location parameters.
| Parameter | Example | Description |
|---|---|---|
gl | "us" | Country code (ISO 3166-1 alpha-2). Affects which Google country domain is used. |
hl | "en" | Language code (BCP-47). Controls the language of results and UI. |
location | "New York, NY" | City/region for precise geo-targeting via Google's uule parameter. |
{
"query": "Tokyo restaurants",
"engine": "google",
"gl": "jp",
"hl": "ja",
"location": "Tokyo, Japan"
}Error Handling
The API uses standard HTTP status codes.
| Code | Meaning |
|---|---|
200 | Success |
400 | Bad request (invalid parameters) |
401 | Missing or invalid API key |
403 | Key revoked or not authorized |
404 | Job not found or expired |
429 | Rate limit exceeded (monthly quota or concurrent limit) |
503 | Service degraded (Redis unavailable) |
Error responses include a detail field with a human-readable message:
{
"detail": "Monthly search limit exceeded (5000/5000). Upgrade plan or wait until next month."
}Rate Limits
Rate limits are enforced per API key at two levels:
- Monthly quota — total searches per calendar month. Resets on the 1st.
- Concurrent requests — maximum simultaneous in-flight searches. Requests above this limit receive a 429.
Check your current usage at any time with GET /v1/usage. When you hit the monthly limit, upgrade your plan from the dashboard or wait until the next month.