Table of Contents
Google Search Console API: Complete Guide
The Google Search Console API gives you programmatic access to the same data you see in the GSC dashboard — impressions, clicks, CTR, average position, coverage status, and more. Instead of manually exporting CSVs or navigating the UI, you can query this data directly from code or third-party tools.
If you've ever hit GSC's row limits, wanted to schedule automated reports, or tried to combine GSC data with other sources (GA4, Sheets, your own database), the API is what unlocks that.
This guide covers everything: what the API provides, how authentication works, what you can query, real use cases, and when it's worth the setup vs using a tool that already handles the API for you.
What Is the Google Search Console API?
The Google Search Console API (also called the Search Analytics API) is a REST API that lets you:
- Query your site's search performance data (queries, pages, countries, devices, dates)
- Check URL indexing status and crawl errors
- Submit URLs for re-indexing (via the Indexing API, a related but separate API)
- Access sitemap data (submit, list, delete sitemaps)
- Retrieve structured data enhancement reports
The most commonly used endpoint is the Search Analytics query endpoint, which mirrors what you see in GSC's Performance report — but without row limits, with full programmatic control, and with the ability to automate.
Google Search Console API vs. Manual GSC
| Feature | GSC Dashboard | GSC API | |---------|---------------|---------| | Row limit | 1,000 rows (UI), 25,000 per query (export) | 25,000 per request; paginate for more | | Date range | Up to 16 months | Up to 16 months | | Automation | Manual only | Fully automatable | | Scheduling | None | Run on cron/schedule | | Data blending | No | Combine with any data source | | Skill required | None | API/coding knowledge or a tool |
When to use the API: Large sites (1,000+ pages), agencies managing multiple properties, developers building SEO tools, anyone who needs scheduled reports or data pipelines.
When the UI is enough: Sites under a few hundred pages, quick one-off analysis, users who don't code.
Authentication: How to Access the GSC API
The GSC API uses OAuth 2.0 for authentication. There are two main approaches:
Option 1: Service Account (Recommended for Automation)
Best for server-to-server access, cron jobs, and production pipelines.
- Go to Google Cloud Console
- Create a new project (or use an existing one)
- Enable the Google Search Console API under APIs & Services
- Create a Service Account under IAM & Admin
- Download the JSON key file
- In Google Search Console, add the service account email as a verified owner or full user of your property
Option 2: OAuth 2.0 User Flow
Best for tools or apps where users authenticate with their own Google accounts.
- Create OAuth 2.0 credentials in Google Cloud Console
- Set redirect URIs for your application
- Implement the OAuth flow to obtain an access token
- Use the access token in API requests
For most automation use cases, service accounts are simpler — no browser interaction required once set up.
The Search Analytics API: What You Can Query
The core endpoint is:
POST https://www.googleapis.com/webmasters/v3/sites/{siteUrl}/searchAnalytics/query
Dimensions
You can break data down by any combination of:
query— search queries (keywords)page— landing page URLscountry— user countrydevice— desktop, mobile, tabletdate— individual datessearchAppearance— rich results, AMP, etc.
Metrics
For each dimension combination, you get:
clicks— number of clicksimpressions— number of impressionsctr— click-through rateposition— average ranking position
Filters
You can filter by any dimension before aggregating. For example:
- Only queries containing a specific keyword
- Only pages matching a URL pattern
- Only mobile device traffic
Date Ranges
Specify startDate and endDate in YYYY-MM-DD format. Data goes back up to 16 months.
Sample API Request (Python)
Here's a minimal example pulling top 10 queries for a site over the last 28 days:
from googleapiclient.discovery import build
from google.oauth2 import service_account
# Authenticate with service account
SCOPES = ['https://www.googleapis.com/auth/webmasters.readonly']
credentials = service_account.Credentials.from_service_account_file(
'service-account-key.json', scopes=SCOPES
)
service = build('searchconsole', 'v1', credentials=credentials)
# Query the API
request = {
'startDate': '2026-01-26',
'endDate': '2026-02-23',
'dimensions': ['query'],
'rowLimit': 10,
'startRow': 0
}
response = service.searchanalytics().query(
siteUrl='https://yoursite.com',
body=request
).execute()
for row in response.get('rows', []):
print(row['keys'][0], row['clicks'], row['impressions'], row['ctr'], row['position'])
This returns the top 10 queries by impression count for your site over the specified date range.
Pagination: Getting More Than 25,000 Rows
The rowLimit maxes out at 25,000. For sites with more queries than that (any moderately large site), you need to paginate using startRow.
def fetch_all_rows(service, site_url, start_date, end_date, dimensions):
all_rows = []
start_row = 0
row_limit = 25000
while True:
request = {
'startDate': start_date,
'endDate': end_date,
'dimensions': dimensions,
'rowLimit': row_limit,
'startRow': start_row,
}
response = service.searchanalytics().query(
siteUrl=site_url, body=request
).execute()
rows = response.get('rows', [])
if not rows:
break
all_rows.extend(rows)
if len(rows) < row_limit:
break
start_row += row_limit
return all_rows
Two things to know: (1) the API caps out at whatever data GSC actually has for that date range — pagination stops naturally when the last page returns fewer rows than the limit. (2) For query-level pulls on very large sites, the API applies the same anonymization GSC does in the UI. Sub-10-impression queries and privacy-filtered queries won't appear no matter how deep you paginate.
Error Handling and Retry Logic
The GSC API is generally reliable, but it will throw 403 quotaExceeded if you burst past the per-100-second rate limit, and occasionally 500/503 on Google's end. Any production script needs backoff:
import time
from googleapiclient.errors import HttpError
def query_with_retry(service, site_url, body, max_retries=5):
for attempt in range(max_retries):
try:
return service.searchanalytics().query(
siteUrl=site_url, body=body
).execute()
except HttpError as e:
if e.resp.status in (429, 500, 503):
wait = 2 ** attempt
time.sleep(wait)
continue
if e.resp.status == 403 and 'quotaExceeded' in str(e):
time.sleep(100) # per-100s window resets
continue
raise
raise RuntimeError("GSC API failed after retries")
Two patterns catch >95% of real-world failures: exponential backoff on 5xx and 429, and a full 100-second sleep on quotaExceeded. Do not silently swallow other 4xx errors — a 403 forbidden on a specific siteUrl usually means the service account was never added as a user on that property, and it will fail forever until you fix the permission.
Node.js Example (for JS/TS Shops)
If your stack is Node instead of Python, the API is identical — different client library:
import { google } from 'googleapis'
const auth = new google.auth.GoogleAuth({
keyFile: './service-account-key.json',
scopes: ['https://www.googleapis.com/auth/webmasters.readonly'],
})
const webmasters = google.webmasters({ version: 'v3', auth })
const response = await webmasters.searchanalytics.query({
siteUrl: 'https://yoursite.com',
requestBody: {
startDate: '2026-01-26',
endDate: '2026-02-23',
dimensions: ['query', 'page'],
rowLimit: 25000,
},
})
for (const row of response.data.rows || []) {
console.log(row.keys, row.clicks, row.impressions, row.ctr, row.position)
}
Same auth model, same request shape, same rate limits. Everything in this guide translates 1:1.
GSC API vs BigQuery Bulk Export
Google added the BigQuery bulk export in 2023, and it's now a serious alternative to hitting the API on a schedule. The two are complementary, not competing:
| | GSC API | BigQuery Export | |---|---|---| | Setup time | 5-10 min | 15-30 min (Cloud project + billing) | | Historical data | 16 months | Only from export date forward | | Query anonymization | Yes (small queries hidden) | Yes (same anonymization) | | Rows returned | 25k/request, paginated | Unlimited SQL over full dataset | | Data freshness | ~2 days behind | ~2 days behind | | Cost | Free | BigQuery storage + query costs (~$1-10/mo for most sites) | | Best for | Ad-hoc pulls, small sites, dashboards | Large sites, decay analysis, joining with other warehouse data |
Rule of thumb: Use the API for anything under 50k queries/day and for real-time dashboards. Use BigQuery for anything where you want to run SQL across months of daily snapshots (content decay, cannibalization, cohort analysis). Enable BigQuery export as soon as you turn on GSC — you can't backfill, so every day you wait is a day of history you'll never have.
The Indexing API: Related but Separate
The Indexing API lives under a different endpoint and is intended for job postings and livestreams, but Google generally accepts submissions from other content types too (though it's not a guaranteed indexing signal — it's a hint):
from googleapiclient.discovery import build
from google.oauth2 import service_account
credentials = service_account.Credentials.from_service_account_file(
'service-account-key.json',
scopes=['https://www.googleapis.com/auth/indexing']
)
service = build('indexing', 'v3', credentials=credentials)
service.urlNotifications().publish(body={
'url': 'https://yoursite.com/new-page',
'type': 'URL_UPDATED',
}).execute()
Quota is 200 URLs/day per project. Pair it with IndexNow (which Bing, Yandex, and Naver honor) and a sitemap lastmod bump for the strongest indexing push you can send without Google Search Central manual submission.
Common GSC API Use Cases
1. Automated Keyword Performance Reports
Schedule a daily or weekly script to pull your top 50 queries, track position changes over time, and email a summary. This gives you historical position tracking without paying for a rank tracker.
2. Find Striking Distance Keywords at Scale
Programmatically pull all queries where position is between 4 and 20 and impressions > 100. These are your highest-priority optimization targets. On large sites, there can be hundreds of these — impossible to find manually in the UI.
3. CTR Analysis by Landing Page
Pull data by page dimension and calculate each page's actual CTR vs. the expected CTR for its average position. Pages underperforming their position benchmark have title or description issues worth fixing.
4. Multi-Site Dashboard
If you manage multiple GSC properties, the API lets you pull data from all of them into a single database or spreadsheet. Compare performance across sites, identify winning patterns, and catch declining properties early.
5. Integration with GA4
Combine GSC clicks and impressions with GA4 sessions and conversions. Identify which search queries drive your most valuable traffic — not just the most clicks.
6. Content Decay Detection
Programmatically compare current performance vs. 90 days ago for every page on your site. Pages where impressions have dropped >30% are candidates for a content refresh.
API Limits and Quotas
- Queries per day: 200 requests per 100 seconds per project (adjustable with quota increases)
- Rows per request: Up to 25,000
- Date range: Up to 16 months of data
- Properties per account: Limited by your GSC verified properties
- Sampling: Data for smaller sites may be sampled at very high row counts
For most SEO use cases, default quotas are more than sufficient.
Quota increase requests go through Google Cloud Console → APIs & Services → Quotas → Search Console API. Approvals for reasonable increases (2-10×) usually come back within 24-48 hours; ask for what you actually need with a concrete use-case description, not the maximum allowed.
Five Traps That Bite Everyone Their First Week
-
Property prefix mismatch.
https://yoursite.comandsc-domain:yoursite.comare different properties in GSC's eyes. If your service account is added to one and you query the other, every response comes back empty with no error. Fix: match the exactsiteUrlstring shown in the GSC property picker. -
Timezone drift. The API returns dates in the property's timezone, but the date range you request is interpreted as UTC. On sites near a day boundary, a "last 7 days" query at 1am UTC can silently include or exclude an entire day of data vs the UI. Fix: always request one extra day and slice locally.
-
The 2-day delay isn't uniform. Country and device dimensions finalize ~2 days behind, but query-level data can stabilize up to 3-4 days later as anonymization thresholds settle. If you're building alerting, don't compare "yesterday vs 8 days ago" — compare
date - 4vsdate - 11to keep the same maturity on both sides. -
Row totals don't equal dimension sums. Sum of per-query clicks for a page will almost always be less than that page's total clicks, because anonymized queries are hidden per-row but counted in totals. Reconciling the gap is how you find your "hidden branded traffic" — see our anonymized queries piece for the math.
-
Silent truncation. If your request returns exactly 25,000 rows and you don't paginate, you almost certainly hit the cap. Always compare
len(response.rows)torowLimit; if equal, keep paginating.
Recipe: Striking-Distance Report in 40 Lines
The most-cited "why do I need the API" workflow — pull every query ranking 4-20 with meaningful impressions:
STRIKING_DISTANCE_MIN_POS = 4
STRIKING_DISTANCE_MAX_POS = 20
MIN_IMPRESSIONS = 100
rows = fetch_all_rows(
service, 'https://yoursite.com',
'2026-01-01', '2026-01-31',
['query', 'page']
)
opportunities = [
{
'query': r['keys'][0],
'page': r['keys'][1],
'position': round(r['position'], 1),
'impressions': r['impressions'],
'clicks': r['clicks'],
'ctr': round(r['ctr'] * 100, 2),
}
for r in rows
if STRIKING_DISTANCE_MIN_POS <= r['position'] <= STRIKING_DISTANCE_MAX_POS
and r['impressions'] >= MIN_IMPRESSIONS
]
opportunities.sort(key=lambda r: -r['impressions'])
for o in opportunities[:50]:
print(o)
Run this monthly, hand the top 50 to your content team, and you'll typically see a 15-30% traffic lift on those pages within 60-90 days from title/description/H1 tightening alone — no new links required.
When to Use the API vs. a Tool
The API is powerful but requires setup, maintenance, and coding knowledge. Search Console Tools (searchconsoletools.com) is built on top of the GSC API and handles authentication, querying, and analysis for you — no code required.
Use the raw API when:
- You're building a custom internal tool or data pipeline
- You need to combine GSC data with proprietary data sources
- You want full control over data storage and processing
- You have engineering resources to build and maintain the integration
Use Search Console Tools when:
- You want striking distance analysis, CTR benchmarking, and content decay detection without writing code
- You're managing 1–50 sites and need fast answers
- You want automated reports in a clean interface
- You want the API's power without the API's complexity
FAQ
Do I need to pay for the Google Search Console API? No. The GSC API itself is free. You pay for Google Cloud (for the OAuth/service account infrastructure), but costs are negligible for typical SEO use — usually under $1/month or free under GCP's free tier.
Can I use the GSC API to submit URLs for indexing? Not directly. URL submission uses the separate Indexing API, which is also free. The two APIs are different — the Search Analytics API reads performance data; the Indexing API notifies Google of URL changes.
How far back does GSC API data go? Up to 16 months. This matches what's available in the GSC dashboard. Data older than 16 months is not accessible through any method.
How many rows can I pull at once?
Up to 25,000 rows per request. For sites with more queries than that, use startRow to paginate through the full dataset.
What's the difference between the GSC API and the Search Console API?
They're the same thing. "Google Search Console API" and "Search Console API" and "Search Analytics API" all refer to the same set of endpoints under googleapis.com/webmasters/v3.
Can I pull GSC data into Google Sheets? Yes — Google Sheets has a built-in Google Analytics connector that includes limited GSC data, but for full control, use the API with Google Apps Script or a Sheets add-on like Supermetrics or Search Analytics for Sheets.
What Python libraries do I need?
Just two: google-api-python-client and google-auth. Install with pip install google-api-python-client google-auth. No other dependencies for the core Search Analytics endpoint. If you want to push results into BigQuery from the same script, add google-cloud-bigquery.
Can a single service account access multiple GSC properties? Yes. Add the service account email as a user on each property in GSC's Users & Permissions screen. One key file, one script, N properties — this is the standard agency/multi-site pattern.
How do I query GSC data alongside GA4 data?
Both APIs use the same Google auth pattern, so you can use the same service account (with analytics.readonly scope added). Pull GSC by page, pull GA4 by pagePath, then join on URL. The typical value is comparing GSC impressions/clicks (top of funnel) to GA4 sessions and conversions (bottom of funnel) to find high-impression pages that don't convert.
Is the Indexing API safe to use for regular pages? Google officially says it's for job postings and livestreams only, and reserves the right to ignore submissions of other content types. In practice, most sites use it for all content with no negative signal — but treat it as a hint, not a guarantee. Pair with IndexNow and internal-link bumps for the strongest signal stack.
When does the API return 403 forbidden?
Almost always a permission issue: either the API isn't enabled in your Cloud project, or the service account isn't added as a user on the target GSC property. Enable the API in Cloud Console → APIs & Services → Library → search "Search Console API" → Enable, then verify the service account email appears in the property's Users list.
Do I need one Google Cloud project per site? No. One project can host credentials that access hundreds of properties. The 200 requests/100s quota is per-project — so if you're managing 50 sites and running heavy pulls, one project may hit limits and you'll either request a quota increase or split into multiple projects.
Run a Free AI Citation Audit
Are you in the AI Overview? Get a free report showing how often ChatGPT, Claude, and Gemini cite your brand, plus the 3 blockers preventing your discovery in 2026.
No spam. 1-click unsubscribe. Join 1,200+ SEO teams managing the GEO pivot.