API Documentation
Guides and references for getting the most out of GeoPeeker
Introduction
This documentation covers how to get the most out of GeoPeeker, from running geo-distributed Peeks and monitors inside the app to wiring those same features into your own tools through our API. Use the links above to jump straight to the section you need.
Most of what you need day to day lives in the app itself: add a site, choose your locations and resolutions, and peek it or set up monitors for DNS, SSL, uptime, and keywords. The sections below focus on the API, for when you want those results inside your own systems.
The API can be used from any language or framework capable of making an HTTP request. The examples below use cURL; adapt them to your HTTP client of choice.
Worker node IP addresses
If your site or firewall restricts inbound traffic, whitelist the GeoPeeker worker nodes below so they can reach your site to take Peeks and run monitors. This list updates as our network changes, so check back here for the current addresses.
- Australia: 15.134.93.110
- Brazil: 52.67.211.138
- California: 18.144.108.46
- Canada: 16.54.180.58
- Germany: 63.188.68.211
- India: 13.204.27.16
- Ireland: 52.210.20.54
- Japan: 52.193.158.189
- Singapore: 56.10.149.205
- Sweden: 16.192.47.13
- United Kingdom: 16.61.183.3
- Virginia: 44.194.250.5
Whitelisting by IP is the reliable way to allow GeoPeeker through a firewall or WAF, since IPs can't be spoofed the way request headers can.
Request headers & user agents
Every HTTP request GeoPeeker makes to your site carries a recognizable User-Agent and an X-Geopeeker-Agent header that names the service behind the request. Use these to spot GeoPeeker in your access logs, exempt it from bot challenges or rate limiting, or tag its traffic in analytics (see how to filter GeoPeeker traffic in your Google Analytics data). Monitor requests also send an X-Geopeeker-Version header.
Peeks send:
User-Agent: GeoPeeker Peek Service/1.0.0 (+https://geopeeker.com/bot; [email protected]) X-Geopeeker-Agent: Peek Service From: [email protected]
HTTP and keyword monitors send:
User-Agent: GeoPeeker HTTP Monitor/1.0.0 (https://geopeeker.com) X-Geopeeker-Agent: HTTP Monitor X-Geopeeker-Version: 1.0.0 User-Agent: GeoPeeker Keyword Monitor/1.0.0 (https://geopeeker.com) X-Geopeeker-Agent: Keyword Monitor X-Geopeeker-Version: 1.0.0
DNS and SSL monitors don't make HTTP requests, so they don't carry these headers. SSL checks connect from the worker node addresses above, so allow them by IP. DNS checks query public DNS and never contact your server.
Because any client can set a User-Agent or an X-Geopeeker-* header, treat these as identification only, not authentication. To actually grant access through a firewall or WAF, whitelist the worker node IP addresses above rather than matching on headers alone.
Authentication
Every plan can create API tokens and call the test endpoint. Creating Peeks through the API requires a paid plan. Create a token on the API Settings page in your GeoPeeker account. The token is shown only once when created, so copy it somewhere safe.
Authenticate every request with a bearer token in the Authorization header:
curl https://geopeeker.com/api/v2/test \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json"
Send Accept: application/json with every request. Without it, errors come back as redirects instead of JSON.
Requests without a valid token return 401. Peek requests from a plan without API access return 403.
Test endpoint
Use the test endpoint to check your token and build against the response format without running a real Peek. It is available on every plan, doesn't count toward your Peek limits, and always returns the same sample data in the shape of a completed Peek, with "test": true added.
GET /api/v2/test
{
"id": "00000000-0000-4000-8000-000000000000",
"url": "https://example.com",
"status": "completed",
"test": true,
"created_at": "2026-09-23T12:00:00.000000Z",
"locations": [
{
"location_id": 0,
"location": "Test Location",
"status": "completed",
"ip": "93.184.215.14",
"ping": 24,
"renders": [
{
"resolution_id": 0,
"image_url": "https://geopeeker.com/logo.png",
"source_url": null
}
],
"dns": {
"A": ["93.184.215.14"],
"NS": ["a.iana-servers.net", "b.iana-servers.net"]
}
}
]
}
Your plan's locations & resolutions
This endpoint lists the location and resolution IDs you can use when taking a Peek, along with the IP addresses of each location's render node, for whitelisting. It is available on every plan.
GET /api/v2/plan
{
"api_peeks": true,
"locations": [
{
"id": 3,
"name": "US West",
"ips": ["203.0.113.10"]
}
],
"resolutions": [
{ "id": 1, "width": 1280, "height": 800 },
{ "id": 7, "width": 1024, "height": 768 }
],
"default_resolution_id": 1
}
api_peeks is false on plans that can't create Peeks through the API. default_resolution_id is the resolution used when a Peek doesn't specify one. A location's ips list is empty until its render node addresses are listed.
Taking a Peek
Peeks are asynchronous: you submit a URL, receive a Peek id immediately, then poll for results. Creating Peeks requires a paid plan.
POST /api/v2/peeks
curl -X POST https://geopeeker.com/api/v2/peeks \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"url": "https://example.com",
"capture_source": true
}'
Body parameters:
url(required): the URL to peek.location_ids(optional): array of location IDs to peek from, as listed by/api/v2/plan. Only locations included in your plan are used; others are ignored, and if none of the IDs are in your plan the request returns422. Defaults to every location your plan includes.resolution_id(optional): a resolution included in your plan, as listed by/api/v2/plan. A resolution outside your plan returns422. Defaults to the largest resolution your plan includes.language(optional): language code (e.g.en-US). An unrecognized code falls back to the default language.capture_source(optional): whentrue, also capture the rendered HTML source of the page (returned assource_url). Available on the Pro, Team, and Enterprise plans; ignored on other plans.
Returns 202 Accepted:
{
"id": "9b1c7d2e-4f3a-4c8b-bb10-3a2e1f6d9c44",
"status": "pending",
"results_url": "https://geopeeker.com/api/v2/peeks/9b1c7d2e-4f3a-4c8b-bb10-3a2e1f6d9c44"
}
Retrieving results
Poll the results URL until status is no longer pending. It becomes completed when every location succeeds, failed when every location fails, or partially_completed when some locations fail.
GET /api/v2/peeks/{id}
curl https://geopeeker.com/api/v2/peeks/9b1c7d2e-4f3a-4c8b-bb10-3a2e1f6d9c44 \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Accept: application/json"
A completed Peek returns per-location renders, the site's IP address and ping, DNS records (grouped by type), and (when requested) the captured source URL:
{
"id": "9b1c7d2e-4f3a-4c8b-bb10-3a2e1f6d9c44",
"url": "https://example.com",
"status": "completed",
"created_at": "2026-06-04T16:30:00.000000Z",
"locations": [
{
"location_id": 3,
"location": "US West",
"status": "completed",
"ip": "104.20.23.154",
"ping": 18,
"renders": [
{
"resolution_id": 1,
"image_url": "https://...s3...amazonaws.com/?X-Amz-Signature=...",
"source_url": "https://...s3...amazonaws.com/_source?X-Amz-Signature=..."
}
],
"dns": {
"A": ["104.20.23.154", "172.66.147.243"],
"AAAA": ["2606:4700:10::6814:179a"],
"NS": ["elliott.ns.cloudflare.com", "hera.ns.cloudflare.com"]
}
}
]
}
image_url and source_url are presigned and expire after about 7 days, so download anything you want to keep. source_url is null unless capture_source was requested. A Peek ID that doesn't exist or belongs to another account returns 404.
ip is the address the site's domain resolved to from that location, and ping is the time in milliseconds to open a connection to it from there. Either is null while the location is pending, or if it couldn't be measured.
Listing recent Peeks
GET /api/v2/peeks returns your 50 most recent API Peeks, newest first.
{
"data": [
{
"id": "9b1c7d2e-4f3a-4c8b-bb10-3a2e1f6d9c44",
"url": "https://example.com",
"created_at": "2026-06-04T16:30:00.000000Z",
"results_url": "https://geopeeker.com/api/v2/peeks/9b1c7d2e-4f3a-4c8b-bb10-3a2e1f6d9c44"
}
]
}
Rate limits & errors
Every API endpoint shares a limit of 60 requests per minute for your account. Going over it returns 429 with {"message": "Too Many Attempts."} and a Retry-After header giving the seconds to wait.
API Peeks have their own allowance, separate from the Peeks you run in the app. It's the same size as your plan's hourly Peek allowance and counts the last 60 minutes. Some plans also have a daily cap. You can see your current usage on the API Settings page. When you exceed it, creating a Peek returns 429:
{
"message": "API peek limit reached for your plan.",
"used_this_hour": 30,
"hourly_limit": 30,
"used_today": 42,
"daily_limit": null
}
Other responses you may encounter:
401 Unauthenticated: missing or invalid token.403: your plan does not include API Peeks. This covers creating, listing and retrieving Peeks. The test and plan endpoints still work.404: the Peek doesn't exist or belongs to another account.422: validation error, such as a missing or invalidurl(details in theerrorsobject), or alocation_idsorresolution_idoutside your plan (details inmessage).503: the Peek couldn't be started. It doesn't count toward your allowance, so try again shortly.