Search Console API: four services, two hostnames, and the row limit that makes it worth using

The Search Console API is free and returns the same numbers as the interface, with one difference worth the setup: 25,000 rows per request instead of a thousand. It is four services on two hostnames, authenticated with OAuth rather than an API key, and its quotas are charged by query shape rather than by call count.

Measurement8 min read2464 views
Search Console API: four services, two hostnames, and the row limit that makes it worth using

The Search Console API is free, and it returns the same numbers you already see in Search Console — with one difference that decides whether you need it: a single request can return 25,000 rows instead of the thousand you can read on screen, and the same call can be scheduled. It is four services, not one, and two of them live on different hostnames, which is the first thing that trips people up.

Before you start

You need a Search Console property you already own, and you need to be able to add an email address to it — either your own, or a service account's. The API does not give you access to anyone's data; it reads the properties your account has. If the property is not verified yet, reading the performance report as five shapes is the cheaper first step, because the API will only hand you the same report in a less friendly form.

You do not need to be a developer to finish this chapter, but you do need to run one command that prints JSON. Everything below is done in a browser and a terminal.

Why the Search Console API is four services on two hostnames

The reference index lists four services, and they were added at different times, which is why the URLs disagree with each other. Search Analytics, Sitemaps and Sites all sit under a path that still carries the product's older name, webmasters/v3. URL Inspection was added later and lives on its own host, searchconsole.googleapis.com, with a different version number.

ServiceWhat it answersEndpoint
Search AnalyticsWhich searches, pages and countries produced impressions and clicksPOST www.googleapis.com/webmasters/v3/sites/siteUrl/searchAnalytics/query
URL InspectionWhat Google's index currently holds for one URLPOST searchconsole.googleapis.com/v1/urlInspection/index:inspect
SitemapsWhich sitemaps are submitted, and their statuswww.googleapis.com/webmasters/v3/sites/siteUrl/sitemaps
SitesWhich properties the account can seewww.googleapis.com/webmasters/v3/sites

Two details in that table cause most of the first-day errors. The property identifier inside the URL is either the exact URL prefix you verified, including the trailing slash, or the domain form sc-domain:example.com — and the two are not interchangeable. And the search analytics method is a POST even though it only reads: the filters and the date range go in a request body, not in a URL string you can paste into a browser.

The API is not a second Search Console. It is the same data with a different ceiling — and the ceiling is the only reason to learn it.

Do it in this order

Four steps, each with something you can check before moving on. The whole sequence takes about twenty minutes the first time and nothing after that.

  1. Turn the API on for a project. In the Google Cloud console, create a project, then enable the Search Console API on it. Done when the API appears as enabled in that project's list.
  2. Create credentials. For a one-off script, an OAuth client of the desktop type is the shortest path, because it can open a browser window and store a refresh token. For anything scheduled on a server, create a service account instead and download its JSON key. Done when you hold either a client secret or a key file on disk.
  3. Grant it access to the property. Open Search Console, go to the property's settings, and add the service account's email address as a user. Done when the address appears in the property's user list with full or restricted permission. Skipping this step produces a 403 that looks like a bug in your code.
  4. Make one call and read the shape of the answer. Ask for one week of data grouped by page, with no filters. Done when you get rows with keys, clicks, impressions, ctr and position.
pip install google-auth google-auth-oauthlib requests

python3 -c "
import json, requests
from google.oauth2.credentials import Credentials

creds = Credentials.from_authorized_user_file('token.json',
          ['https://www.googleapis.com/auth/webmasters.readonly'])
site = 'sc-domain:example.com'
body = {'startDate': '2026-09-07', 'endDate': '2026-09-13',
        'dimensions': ['page'], 'rowLimit': 25000, 'dataState': 'final'}
url = 'https://www.googleapis.com/webmasters/v3/sites/' + site + '/searchAnalytics/query'
r = requests.post(url, headers={'Authorization': 'Bearer ' + creds.token}, json=body)
rows = r.json().get('rows', [])
print(len(rows), 'rows')
for row in rows[:5]:
    print(round(row['clicks'], 1), row['keys'][0])
"

The deliverable: a routing table, and the two ceilings it has to live inside

Keep this table next to the one above. It is the part that saves time, because the three ways of pushing or reading data are constantly confused with each other, and each one has a different set of rules about who may use it.

JobWhat to useWho may use it
Read impressions and clicks in bulkSearch AnalyticsAny verified property
Check one URL's index status at scaleURL Inspection serviceAny verified property
Ask Google to recrawl a pageThe URL Inspection tool in the interfaceAny verified property
Push a URL the moment it changesIndexNowAny site; Bing and Yandex read it
Push a job posting the moment it changesIndexing APIJob postings and live streams only
List or resubmit sitemapsSitemaps serviceAny verified property

Note the two rows in the middle, because they are the ones people get wrong. The Indexing API is not a general-purpose push button; if you are not publishing job postings or live streams, it is documented as not applying to you, and the Indexing API chapter covers what to use instead. There is also no documented API method for the URL Inspection tool's live test — the service returns the status of the version already in the index.

The two ceilings are easier to work with than they look, because they fail loudly. Every quota failure returns the same message, so you cannot tell them apart from the error alone; you have to know which one you are likely to be hitting.

CeilingLimitMeasured over
Search Analytics, per property1,200Calls per minute
Search Analytics, per user1,200Calls per minute
Search Analytics, per project30,000,000Calls per day
URL Inspection, per property2,000Calls per day
URL Inspection, per property600Calls per minute
All other resources, per user20Calls per second

There is a second kind of limit underneath the call counts, and it is the one that actually bites: a request is charged by how much work it represents, not by how many times you send it. Grouping or filtering by page and by search term in the same request is documented as the most expensive shape, and a long date range costs more than a short one. A script that asks for two years of data grouped by page and search term will exhaust its budget long before it exhausts its call count.

What goes wrong, and how you would notice

Three failures cover almost everything people hit in the first week, and each one looks like a different problem than it is. All three are visible from the error text alone if you know which question to ask.

  1. A 401 that is really a wrong credential type. API keys identify a project; they do not identify a person, and this API reads private data. If you pasted a key into a header, you get a 401. The fix is an OAuth token from step 2, not a new key.
  2. A 403 that is really missing access. A service account is a separate identity with its own email address, and it starts with access to nothing. Adding it as a user of the property in Search Console is a separate action from creating it, and it is the one that gets skipped.
  3. A quota error that is really a request shape. If a single call inside a ten-minute window fails on quota, you are not hitting the per-minute limit — you are hitting the long-term one, and the fix is to remove the grouping rather than to slow down.

One boundary worth writing down rather than discovering: this chapter covers the four services the reference index lists. If a report is not one of those four, there is no documented API for it, and that includes the generative AI reporting, whose limits are a separate subject. The short version is in the AI Mode reporting chapter: the report answers a question about surfaces, not about individual searches.

We also could not find a documented retention window on the API pages we read, so this chapter does not state one. If you are building anything that must survive a change in that window, the safe pattern is the same as it is for any external data source: pull on a schedule and keep your own copy. Recording a baseline before you change anything is that pattern written out for a single page.

Common questions

Is the Search Console API free?

Yes. There is no price attached to it; the limits above are the only cost, and they are limits on volume rather than on money. You do need a Google Cloud project, but that is an administrative container, not a paid product.

Do I need an API key?

No, and an API key will not work here. An API key identifies a project for public data. Search Console data belongs to a person or an organisation, so every call carries an OAuth 2.0 token, and the token carries one of two scopes: read and write, or read only.

Can I use a service account instead of signing in every time?

Yes, and for anything that runs on a schedule you should. The service account gets its own email address, which you then add as a user of the property in Search Console. The credentials never expire the way a user token does, which is the whole point.

How many rows can one request return?

25,000, and the default is 1,000 if you do not ask. Rows beyond that come from a second request that starts where the first one stopped, using the offset parameter. Most sites never need the offset; a site with a large number of pages and search terms will.

Why do I get the same error message for every kind of quota failure?

Because Google returns one message for all of them. The way to tell them apart is the shape of the failure: a call that fails on its own inside a ten-minute window is a long-term budget problem, and a call that fails only when your script runs flat out is a rate problem.

Part of the QueryWin handbook · Level 2

Search Console API: four services, two hostnames, and the row limit that makes it worth using