Search Console API
Google Search Console API limits, and what you still have to build.
The quotas are generous and the rows are free. The weekend goes on what comes after the client: a store that outlives the 16-month wall, a diff Google has no endpoint for, and a verdict on which page to open first.
From $49/mo, everything included · works in Claude Code, Cursor, Cline and Windsurf
Quota figures on this page are Google's. The rest comes from the Search Console code we run in production every day.
The actual numbers
The API limit is four ceilings, not one.
They fail in four different ways, and only one of them announces itself. Mixing them up is the reason most first scripts quietly return a partial answer and get believed.
Rows per request
25,000
The rowLimit parameter accepts 1 to 25,000 and defaults to 1,000. That default is the trap: leave it out and you get the first thousand rows with no error and no flag. Page through with startRow until a batch comes back short.
Fails silently. You get a number, just not the whole one.
Query rate
1,200 QPM
For Search Analytics, per site and per user alike, inside a project ceiling of 40,000 QPM. There is also a load quota measured in 10-minute and 1-day chunks, which complex queries burn faster: a page and query join over a long date range is expensive.
Fails loudly. You get an error you can retry.
URL inspections
2,000 / day
Also capped at 600 a minute, per property. This is the one you will actually hit, because it is per URL rather than per query, and indexing questions are exactly the ones you want to ask about every page. A 5,000-page site cannot be inspected in a day.
Fails loudly, then costs you days of calendar time.
History
16 months
Not a quota at all, which is why it never appears on the limits page, and it is the one that actually costs you something. Month 17 is gone, permanently, and there is no endpoint that tells you what changed since yesterday. If you want either, you store the data yourself, starting today.
Never fails. It just quietly forgets.
Every figure above is Google's, from the Search Console API usage limits and the searchAnalytics.query reference. Two of them are constants in our own code: we request 25,000 rows a call when we backfill a site's history, and we hold each daily inspection run well under the 2,000.
Search Console API rate limits and quotas, in full
QPM is queries per minute, QPD queries per day, and none means Google publishes no cap at that level. Per site counts every call about one property, per user every call one Google account makes, per project every call made with one Cloud project's key. The tightest one that applies is the one you hit.
| API | Scope | QPM | QPD |
|---|---|---|---|
| Search analytics | Per site | 1,200 | none |
| Search analytics | Per user | 1,200 | none |
| Search analytics | Per project | 40,000 | 30,000,000 |
| URL Inspection | Per site | 600 | 2,000 |
| URL Inspection | Per project | 15,000 | 10,000,000 |
| Other calls | Per user | 200 | none |
| Other calls | Per project | none | 100,000,000 |
Other calls (the sites and sitemaps resources) are also capped at 20 a second per user. Search Analytics also carries a load quota with no published number: a short-term one measured in 10-minute chunks and a long-term one measured in 1-day chunks. A request grouped or filtered by page and query together, over a long date range, uses up far more of it than a one-day site total.
When you hit the limit
Every overage returns the same quota exceeded error, whichever ceiling you crossed, so the error alone does not tell you which one it was. Google's own advice tells them apart:
- Wait 15 minutes and try again. If the retry works, you hit the short-term quota: spread the same queries across the day instead of firing them in a burst.
- Still refused, or refused on a single query in a 10-minute window? That is the long-term quota. Drop the page or query grouping you do not need, shorten the date range, and stop re-pulling data you already have.
- Hit 2,000 inspections on one property? Nothing resets it before tomorrow. Inspect the pages that matter first and carry the rest over.
The cheapest fix for all three is to store what you pulled. Last month's rows do not change once Search Console finalises them, so a script that re-reads them every run is spending quota on an answer it already has.
Scope
Where the API beats the export, and where it stops.
Only in the API
- +The exact page and query join. Ask for both dimensions at once and every row carries both keys. The interface cannot show you this and no CSV export produces it.
- +Hourly rows, through a separate data-state value, which is how the last-24-hours view is built.
- +Search appearance, the rich-result types you win. Group by it and the response lists the values your property actually has.
- +Discover as a separate surface. It carries clicks and impressions but no queries and no position, because nothing there is ranked.
Where it stops
- −Links. The backlink report is interface-only, so there is no endpoint for who links to you.
- −Anything about a competitor. It is your property or nothing, which also means it cannot see the results page you are ranking on.
- −The page indexing report as a whole. You reconstruct coverage one URL at a time, against that 2,000 a day cap.
- −Crawl stats and Core Web Vitals. Both are reports in the interface with no API behind them, so a tool that shows you page speed beside your rankings got it from somewhere else.
- −The rare queries. Google leaves them out of the query table to protect the searcher's privacy, so the query table totals less than your real clicks. No quota causes this and no parameter turns it off.
That last one is the one that bites hardest, because it looks like data rather than a gap. If you sum query rows to get a site total, you will under-report your own traffic and never see an error. Page-level and query-level data are not interchangeable, and the rule that falls out of it is the one QueryScope is built on: take volume and change from the page dimension, and read queries for alignment and intent only.
Three things the documentation is right about and still does not prepare you for.
Each of these cost us a real debugging session. If the vocabulary is unfamiliar, the Search Console glossary defines every metric and indexing state in a sentence, with the caveat that makes it misleading.
The API and the interface disagree, and both are correct.
One setting decides whether a response includes the freshest days or only finalized ones, and it changes the totals for the same site over the same dates. We take finalized data for the stored weekly snapshot, because a week-over-week diff has to compare like with like, and fresh data for everything read live, because that is what the interface shows. Same endpoint, two answers, no bug. Nearly every thread about numbers that do not match is this parameter.
finalized: stable, trails ~3 days · fresh: matches the interface
Why Search Console throws the history awayWe anchored a 24-hour window to now(). It reported 1 click instead of 7.
The hourly pipeline trails the present by a few hours, so a window ending at the current time slices off the hours that actually carry the traffic and counts empty recent hours in their place. It under-reports badly and it never errors, which is why it survived review: the number looked plausible. The fix is to anchor the window to the latest hour that has data, not to the clock. The comment explaining it is still in our sync code, because the next person deserves to find it.
now() anchor: 1 click · latest-hour anchor: 7 clicks
What we found running this on a real SaaSA domain property and a URL-prefix property are different properties.
The same site can be verified as sc-domain:example.com, as https://example.com/, or with the www or http spelling, and the wrong one returns a 403 rather than an empty result. Guessing is not viable, so we list the properties the credential can actually read and match against the candidates in order. Two minutes of reading beats an afternoon spent debugging an authentication error that was never about authentication.
list the properties first · never guess the string
Connect it over MCP insteadTwo ways to get there
The API is free. The layer on top of it is the actual project.
Writing the client is an afternoon and it is a genuinely good afternoon. What follows it is a store, a daily job, a diff, and the judgment call about which of forty pages to open first. QueryScope is that layer, already built, against the same free API.
Write it yourself
Free, and yours to keep running.
Connect QueryScope
One line, hosted, and the decision made.
What the layer actually is
Five tools in your editor, not a dashboard to alt-tab to. keyword sizes the searches your agent reads out of your repo: how many people search each one, where you stand, and who ranks above you. focus records what the site sells and to whom, and renders the plan to queryscope.md in your repo: a change to what a visitor reads waits for your commit, which is what agrees to it. verdict records what you decided about each search. work is the loop after that, one target at a time, and it will not hand the next one back while a change is still settling, because a second edit inside that window destroys the measurement of the first. history hands your agent the stored series behind all of it, past the 16-month wall, as tables.
Below position 10 Search Console records nothing at all, no impression and no position, so for the searches you declared QueryScope reads the results page directly and fills that dark half. The seam is hard: every page-1 position on your screen came from Search Console, a crawl is only ever used below 10, and the two are never mixed. It stops at the click, it writes no content, and it never touches your repo: your own agent makes every edit.
One line in your IDE. Then authorize and pick a site.
claude mcp add --transport http queryscope https://mcp.queryscope.dev/mcp
Works the same in Cursor, Cline and Windsurf. Your IDE opens a browser once to authorize.
Then ask: “what should I work on?”
Keep the API. Skip the layer on top of it.
Same data, same read-only grant, already paginated, stored past the 16-month wall, and worked one search at a time.
7-day free trial · nothing due today · cancel in one click
FAQ
Search Console API questions.
Is the Google Search Console API free?
Yes. There is no charge and no billing account required, only quotas. That is exactly why the interesting question is not what the API costs but what you build on top of it: the storage, the daily job, and the decision about what to fix are the parts that take real time.
How many rows can I get per request?
Up to 25,000, but the default is 1,000 and it applies silently if you leave the parameter out. Page through with the start-row offset and stop when a batch returns fewer rows than you asked for. If you cap your own pagination, log it when you hit the cap: a truncated result that looks complete is worse than an error.
Why does my API data not match the Search Console interface?
Usually the data-state setting. Finalized data trails roughly three days and stays stable; fresh data includes the most recent days and is what the interface shows by default, so the same query over the same dates returns different totals. The second common cause is summing query rows: Google leaves rare queries out of the query table for privacy, so query totals are always lower than page totals.
Can I get backlinks or competitor data from the Search Console API?
No, and no. The links report exists only in the interface, and the API is scoped to properties you have verified access to, so competitor data is out of reach by design. QueryScope fills exactly one part of that gap and says where it came from: for the searches you declared it reads the results page directly, which is how it can tell you an AI Overview or a rival sits above you. Every page-1 position still comes from Search Console, and a crawl is only ever used below position 10.
How far back does the Search Console API go?
Sixteen months, and it rolls forward, so month 17 is deleted rather than archived. There is also no endpoint for what changed since yesterday. Both are reasons to start storing your own daily copy today rather than the day you need the comparison, which is usually the day it is already too late. QueryScope backfills the full window on connect and keeps a daily snapshot from then on, so the history outlives the wall.
Does QueryScope write content or change my site?
No. It never touches your repo and generates no content: your own agent makes every edit. QueryScope holds the plan, reads your Search Console, says which search to work next and what to change, then starts the measurement clock the day Google recrawls the page. It also stops at the click, so it will never tell you a ranking change earned you a signup.