The Search Console API provides programmatic access to Search Analytics, Sites, Sitemaps, and indexed URL Inspection. It can automate performance extraction, property discovery, sitemap administration, and sampled index checks, but it does not expose every Search Console report or UI action.
Correct use requires more than a successful HTTP response. The client must preserve property scope, Search type, aggregation, filters, data state, privacy limits, and quota behavior so that the result still means what the analyst thinks it means.
What the API includes
| Service | Supported work | Important boundary |
|---|---|---|
| Search Analytics | Query clicks, impressions, CTR, and position by supported dimensions and filters | Returns bounded top rows, not an unlimited census |
| Sites | List, get, add, or remove properties associated with the account | Adding a property does not complete ownership verification |
| Sitemaps | List, get, submit, or delete submitted sitemaps | Submission is a discovery hint, not an indexing guarantee |
| URL Inspection | Retrieve Google’s indexed evidence for a URL | Does not run a live test or request indexing |
There are no general public endpoints for Page Indexing, Core Web Vitals, Links, Manual Actions, Security Issues, Removals, or the rich-result report tables. Do not imitate those reports by giving unrelated API data the same label.
Set up authorization with least privilege
Search Console API requests that access user data require OAuth 2.0. Create a Google Cloud project, enable the Search Console API, create credentials for the application type, and complete the appropriate OAuth flow.
Use one of two scopes:
https://www.googleapis.com/auth/webmasters.readonlyfor read-only access;https://www.googleapis.com/auth/webmasterswhen the application genuinely needs write actions such as sitemap submission or property changes.
Prefer the read-only scope for reporting. The authenticated principal must also have sufficient Search Console permission on the target property. OAuth consent does not grant property access by itself.
For unattended applications, protect refresh tokens or service-account credentials in a secret manager, rotate access deliberately, and give the automation principal access only to required properties. Never place credentials in source code, logs, or exported reports.
Treat the property identifier as data
The siteUrl is the exact property identifier returned by the Sites service:
- URL-prefix property:
https://www.example.com/ - Domain property:
sc-domain:example.com
Do not silently convert one to the other. Encode the property identifier correctly when it appears in a URL path. A mismatch can produce permission errors or query a narrower property than intended.
Begin an integration by calling Sites list, storing each returned permission level, and requiring an explicit property choice.
Build a Search Analytics request
The query method is an authorized POST to the property’s searchAnalytics/query endpoint. A minimal request is:
{
"startDate": "2026-06-01",
"endDate": "2026-06-30",
"type": "web",
"dimensions": ["date"],
"aggregationType": "byProperty",
"dataState": "final",
"rowLimit": 25000,
"startRow": 0
}
Dates are inclusive and interpreted in Pacific Time. Omitted dataState defaults to finalized data.
Choose Search type explicitly
Search type separates datasets such as web, image, video, News, Discover, and Google News where supported. Never sum different surfaces into a single “organic search” metric without naming the construction. Run separate requests and label the result.
Add only dimensions the question needs
Common dimensions include date, hour, query, page, country, device, and search appearance. Every added dimension creates a more granular row set and can increase truncation or privacy effects.
Examples:
datefor a stable trend;page,datefor landing-page monitoring;query,pagefor page competition analysis;country,devicefor audience segmentation.
If the decision needs only a property total, do not request query and page “just in case.” Low-dimensional queries are easier to reconcile and less likely to hit row limits.
Use filters deliberately
dimensionFilterGroups combine filters. Supported dimensions and operators depend on the request; query and page filters can use exact, contains, not-contains, and regex-style matching described in the reference.
Persist the complete filter definition with every extract. A report labeled “non-brand” is not reproducible unless its expressions, case behavior, exclusions, and version are stored.
Query filters can change totals because protected anonymized queries have no query text to match. Page filters also change aggregation from the property view.
Understand aggregation before comparing results
aggregationType controls whether appropriate values are aggregated by property or page. Use auto when page grouping or filtering requires it; use an explicit supported type when the analytical contract requires one.
Property-level and page-level totals can differ because Search Console calculates site and URL impressions differently. Performance is generally credited to canonical URLs. The response’s aggregation type is part of the data and should be stored, not inferred later.
Never calculate overall CTR by averaging row CTR values. Use:
total CTR = SUM(clicks) / SUM(impressions)
Average position is also impression-weighted. Do not average averages across rows or periods.
Handle rows, pagination, and data state
rowLimit accepts 1–25,000 and defaults to 1,000. startRow is a zero-based offset. Continue the identical request until a response contains fewer than the requested rows; if a full page lands exactly on the boundary, the next request can return zero rows.
Pagination does not remove the Search Analytics limit of 50,000 top rows per day per Search type. Detailed query/page extracts can therefore remain incomplete after every available page has been collected.
Data states are:
final: finalized data; also the default;all: includes fresh daily data that can still change;hourly_all: includes hourly detail and potentially incomplete hours.
When fresh data is requested with the matching date or hour dimension, inspect response metadata for first_incomplete_date or first_incomplete_hour. Values from that point onward can change noticeably. Production pipelines should upsert them later rather than append duplicates.
Use the other services safely
Sites
Use list to discover the authorized property set and permission level. add and delete change the account’s property list; they do not prove ownership or delete the site from Google Search. Keep those write methods out of reporting-only credentials.
Sitemaps
Use list or get to retrieve submitted sitemap metadata. submit tells Google where a sitemap is; it neither validates every URL nor guarantees crawling or indexing. delete removes the submission record from Search Console, not the sitemap file or indexed URLs.
URL Inspection
Send an inspectionUrl, the exact containing siteUrl, and optionally a language code. The response can include indexed coverage, crawl, canonical, mobile-usability, and rich-results evidence when available.
It reflects the version in Google’s index. It is not equivalent to Test live URL, does not return a complete property inventory, and cannot request indexing. Use it for prioritized samples, not a continuous crawl of every URL.
Plan around current quotas
Google documents both load and request-rate limits. Current headline quotas include:
- Search Analytics: 1,200 queries per minute per site and per user; 40,000 per minute and 30,000,000 per day per project;
- URL Inspection: 600 per minute and 2,000 per day per site, with higher project-level ceilings;
- other resources: 20 queries per second and 200 per minute per user.
Search Analytics load also rises with expensive requests, especially long date ranges. The same quota-exceeded error can represent different quota types.
Use smaller date partitions, cache finalized results, avoid requesting unchanged history, cap concurrency per property, and apply exponential backoff with jitter to retryable failures. Monitor the Google Cloud quota page rather than coding only to published ceilings.
A production extraction contract
For every job, record:
- property identifier and permission context;
- request start and end dates;
- Search type, dimensions, filters, aggregation, and data state;
- extraction time and code/schema version;
- incomplete-data metadata;
- number of rows and whether the 50,000-row boundary was reached;
- API errors, retries, and final job status.
Store data with an idempotent key based on the complete dimensional grain. Re-running a date should replace or merge that partition, not duplicate it.
Validation checklist
Before trusting an integration:
- Compare a simple finalized daily total with the same UI property and Search type.
- Confirm Pacific Time boundaries.
- Add one dimension at a time and explain any total change.
- Verify CTR and position aggregation with raw clicks and impressions.
- Test an empty page after the final pagination offset.
- Force a retryable error and verify bounded backoff.
- Confirm that fresh rows are updated when they become final.
- Alert when a daily extract is absent, unexpectedly empty, or reaches a known row cap.
Common API mistakes
- Using an API key instead of OAuth 2.0 for private Search Console data.
- Requesting the write scope for a reporting job.
- Hard-coding a URL-prefix when the intended property is a Domain property.
- Calling 25,000 rows “all data.”
- Pulling 16 months on every run instead of caching finalized days.
- Averaging CTR or position row values.
- Treating URL Inspection as live inspection or a request-indexing endpoint.
- Assuming a successful sitemap submission means its URLs are indexed.
- Claiming that UI-only reports are available through the API.
Related guides
- GSC UI vs API vs BigQuery
- Pagination, quotas & data states
- Automate Search Console monitoring
- URL Inspection: complete guide