Google Maps API 403 Forbidden & Timeout Errors: Complete Troubleshooting Guide
Fix Google Maps API 403 errors fast: enable billing, whitelist your domain/IP, check API key restrictions, and resolve timeout issues in under 10 minutes.
- A 403 Forbidden from the Maps API almost always means the API key is missing, restricted to wrong domains/IPs, or the associated GCP project has billing disabled or the Maps API not enabled.
- Timeouts (OVER_QUERY_LIMIT or network-level) are caused by exceeding requests-per-second quotas, missing exponential back-off, or slow client-side rendering of large datasets.
- Quick fix checklist: (1) verify billing is active in GCP Console, (2) confirm the Maps JavaScript/Geocoding/etc. API is enabled, (3) check HTTP referrer and IP restrictions on the key, (4) rotate or create a fresh key, (5) add retry logic with exponential back-off for timeouts.
| Method | When to Use | Time to Apply | Risk |
|---|---|---|---|
| Enable billing on GCP project | Maps API was never billed or trial expired | 2 min | Low — no code change |
| Add allowed HTTP referrer | Key restricted and production domain not listed | 1 min | Low — affects key security posture |
| Whitelist server IP | Server-side API calls blocked by IP restriction | 2 min | Low — may expose key if IP range is too broad |
| Create unrestricted key (dev only) | Rapid local debugging only | 1 min | High — never deploy to production |
| Enable specific Maps API service | Service (Geocoding, Places, etc.) not enabled in GCP | 2 min | None |
| Implement exponential back-off | Getting OVER_QUERY_LIMIT or timeout errors at scale | 30 min | Low — pure code addition |
| Increase quota via GCP Console | Legitimate traffic exceeds default QPS limits | 1 day (Google review) | None |
Understanding Google Maps API 403 and Timeout Errors
The Google Maps Platform returns HTTP 403 Forbidden when the request cannot be authorized. This is distinct from HTTP 401 (missing credentials) — 403 means credentials were presented but rejected. The JSON error body typically looks like:
{
"error": {
"code": 403,
"message": "The caller does not have permission",
"status": "PERMISSION_DENIED"
}
}
For client-side Maps JavaScript API, the browser console shows:
Google Maps JavaScript API error: RefererNotAllowedMapError
Google Maps JavaScript API error: ApiNotActivatedMapError
Google Maps JavaScript API error: BillingNotEnabledMapError
Timeouts manifest differently: the HTTP response status is 200 but the JSON body contains "status": "OVER_QUERY_LIMIT", or the network request simply hangs until the browser or server timeout fires.
Step 1: Identify the Exact Error
Browser DevTools (Maps JavaScript API)
Open Chrome DevTools → Console. Google Maps injects descriptive error codes directly into the console. Copy the exact error code (e.g., RefererNotAllowedMapError) and cross-reference the Maps JavaScript API error codes reference.
Server-side / REST API calls
Capture the raw HTTP response:
curl -v "https://maps.googleapis.com/maps/api/geocode/json?address=New+York&key=YOUR_API_KEY" 2>&1 | grep -E '(HTTP|error|status|message)'
A 403 response will show:
< HTTP/2 403
{"error":{"code":403,"message":"API keys with referer restrictions cannot be used with this API.","status":"PERMISSION_DENIED"}}
Step 2: Check GCP Project Billing
This is the single most common cause of sudden 403 errors — the free trial expires or a billing account is detached.
- Open console.cloud.google.com and select your project.
- Navigate to Billing in the left sidebar.
- Confirm a billing account is linked and the account is active (not suspended).
- If billing is disabled, click Link a billing account and follow the prompts.
After re-enabling billing, Maps API calls typically resume within 5 minutes without any code changes.
Step 3: Verify the API Is Enabled
Each Maps Platform product (Maps JavaScript API, Geocoding API, Places API, Directions API, etc.) must be individually enabled.
- In GCP Console go to APIs & Services → Library.
- Search for the specific API you're calling (e.g., "Geocoding API").
- Click it — if the button says Enable, click it. If it says Manage, it's already enabled.
Alternatively via gcloud:
# List enabled APIs
gcloud services list --enabled --project=YOUR_PROJECT_ID | grep maps
# Enable Geocoding API
gcloud services enable geocoding-backend.googleapis.com --project=YOUR_PROJECT_ID
# Enable Maps JavaScript API
gcloud services enable maps-backend.googleapis.com --project=YOUR_PROJECT_ID
Step 4: Audit API Key Restrictions
Go to APIs & Services → Credentials and click your API key.
HTTP referrer restrictions (browser keys)
If you see restrictions like https://example.com/*, the key will 403 for:
http://example.com(wrong scheme)https://www.example.com(www prefix not listed)https://staging.example.com(subdomain not listed)localhost:3000(local dev not listed)
Add all needed patterns:
https://yourdomain.com/*
http://yourdomain.com/*
https://www.yourdomain.com/*
https://staging.yourdomain.com/*
http://localhost/*
IP address restrictions (server keys)
For server-side API calls, the outbound IP of your server must be listed. Find your server's IP:
curl -s https://api.ipify.org
# or on the server itself:
whoami && curl -s ifconfig.me
Add that IP (or CIDR range) to the key's IP restriction list in GCP Console.
API restriction mismatch
If the key has an API restriction (only allowed to call specific APIs) and you're calling an API not in that list, you get 403. Either add the API to the restriction list or use a key with no API restriction.
Step 5: Rotate the API Key (if compromised)
If your key was exposed in a public repository or logs, revoke it and create a new one:
# Using gcloud
gcloud alpha services api-keys delete KEY_ID --project=YOUR_PROJECT_ID
# Create new key
gcloud alpha services api-keys create \
--display-name="Maps Production Key" \
--allowed-referrers="https://yourdomain.com/*" \
--api-target=service=maps-backend.googleapis.com \
--project=YOUR_PROJECT_ID
Update the key in your app config/secrets manager and redeploy.
Step 6: Fix Timeout and OVER_QUERY_LIMIT Errors
The OVER_QUERY_LIMIT status means you've exceeded the requests-per-second (RPS) rate for your quota tier. The default is 50 QPS for most APIs on a paid account.
Check current quota usage:
# View quota metrics in GCP
gcloud monitoring metrics list --filter="metric.type=serviceruntime.googleapis.com/quota/rate/net_usage" 2>/dev/null
# Easier: GCP Console → APIs & Services → Quotas
Implement exponential back-off (Node.js example):
async function geocodeWithBackoff(address, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const res = await fetch(
`https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(address)}&key=${process.env.GOOGLE_MAPS_API_KEY}`
);
const data = await res.json();
if (data.status === 'OK') return data;
if (data.status === 'OVER_QUERY_LIMIT') {
const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500;
console.warn(`OVER_QUERY_LIMIT — retrying in ${delay}ms (attempt ${attempt + 1})`);
await new Promise(r => setTimeout(r, delay));
continue;
}
throw new Error(`Geocoding failed: ${data.status} — ${data.error_message || ''}`);
}
throw new Error('Max retries exceeded for geocoding request');
}
Request a quota increase:
If legitimate traffic exceeds defaults, go to APIs & Services → Quotas, select the quota line (e.g., "Geocoding API — Requests per day"), and click Edit Quotas to submit a quota increase request to Google.
Step 7: Validate the Fix End-to-End
# Test geocoding from the server that will make the call
curl -s "https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway&key=YOUR_KEY" | python3 -m json.tool | grep -E '(status|formatted_address)'
# Expected output:
# "status": "OK",
# "formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA"
If you still see 403, double-check that the curl command runs from the same IP/server environment that production uses (not your laptop).
Frequently Asked Questions
#!/usr/bin/env bash
# google-maps-api-403-diag.sh
# Diagnose Google Maps API 403 and timeout errors
# Usage: API_KEY=your_key bash google-maps-api-403-diag.sh
set -euo pipefail
KEY="${API_KEY:-REPLACE_WITH_YOUR_KEY}"
BASE="https://maps.googleapis.com/maps/api"
echo "=== 1. Geocoding API health check ==="
curl -s "${BASE}/geocode/json?address=New+York&key=${KEY}" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print('STATUS:', d.get('status')); print('ERROR:', d.get('error_message','none'))"
echo ""
echo "=== 2. Places API health check ==="
curl -s "${BASE}/place/findplacefromtext/json?input=Google+HQ&inputtype=textquery&key=${KEY}" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print('STATUS:', d.get('status')); print('ERROR:', d.get('error_message','none'))"
echo ""
echo "=== 3. Directions API health check ==="
curl -s "${BASE}/directions/json?origin=New+York&destination=Boston&key=${KEY}" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print('STATUS:', d.get('status')); print('ERROR:', d.get('error_message','none'))"
echo ""
echo "=== 4. Check server outbound IP (for IP restriction whitelist) ==="
echo "Your outbound IP: $(curl -s https://api.ipify.org)"
echo ""
echo "=== 5. GCP — list enabled Maps APIs (requires gcloud auth) ==="
if command -v gcloud &>/dev/null; then
PROJECT=$(gcloud config get-value project 2>/dev/null || echo 'NOT_SET')
echo "Active project: ${PROJECT}"
gcloud services list --enabled --filter="name:maps OR name:geocoding OR name:places OR name:directions" 2>/dev/null || echo 'gcloud not authenticated — skip'
else
echo 'gcloud CLI not found — install from https://cloud.google.com/sdk'
fi
echo ""
echo "=== 6. Quota / rate limit stress test (5 rapid calls) ==="
for i in {1..5}; do
STATUS=$(curl -s "${BASE}/geocode/json?address=Boston&key=${KEY}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status','ERR'))")
echo " Call ${i}: ${STATUS}"
done
echo ""
echo "Diagnosis complete. If any STATUS is PERMISSION_DENIED: check billing + API enabled."
echo "If OVER_QUERY_LIMIT: implement back-off. If REQUEST_DENIED: check key restrictions."
Error Medic Editorial
The Error Medic Editorial team is composed of senior DevOps engineers, SREs, and cloud architects with combined experience across Google Cloud, AWS, and Azure. We specialize in API integration debugging, quota management, and production incident response. Our guides are written from real on-call experience and validated against official platform documentation.
Sources
- https://developers.google.com/maps/documentation/javascript/error-messages
- https://developers.google.com/maps/api-security-best-practices
- https://developers.google.com/maps/documentation/geocoding/usage-and-billing
- https://cloud.google.com/apis/docs/system-parameters
- https://stackoverflow.com/questions/14804963/google-maps-api-over-query-limit-per-second-limit
- https://issuetracker.google.com/issues/35823434