The Search Console API problems that cost people an afternoon

Updated 12 September 2026

The Google Search Console API is small, well documented and much harder to get working than either of those facts suggests. Almost everybody hits the same half-dozen walls, usually in the same order, and the error messages are unhelpful in a specific way: several completely different causes produce the same 403. This guide is the list, with what each one actually means.

We make a hosted connector that reads this API for you, so read the last section knowing that. Everything before it is about the API itself and is true whether or not you ever use ours.

The four different 403s

A 403 from this API is not one error. It is at least four, and they need different fixes.

"User does not have sufficient permission for site X." The credential authenticated fine and the account behind it is not a verified owner or user of that property. This is the common one for service accounts, because creating a service account does not give it access to anything — you have to take its generated email address and add it as a user in the Search Console UI, on each property, by hand. Nothing about the setup hints that this step exists.

"Request had insufficient authentication scopes." The token is valid but was minted without webmasters.readonly. If you changed the scopes in your code after the first successful sign-in, you are almost certainly still holding the original refresh token, which carries the original scopes. Delete the stored token and re-consent; the scopes are baked in at grant time and adding them to the request does nothing.

"Search Analytics load quota exceeded." Not a permissions problem at all, despite the status code. You are running too many concurrent or too many heavy queries against one property. Serialise them, and cache what you already fetched — the same report requested twice in a minute is the usual cause.

A 403 with an HTML body rather than JSON. The API is not enabled on the Cloud project the credential belongs to, so you are being answered by the API gateway rather than by Search Console. Enable the Search Console API on that specific project, and check you enabled it on the project the key actually belongs to rather than the one you had open.

The 1,000-row ceiling is not the limit you think

searchAnalytics.query returns at most 1,000 rows per call, and a great many people conclude their site only has 1,000 queries. It does not. You page through with startRow, requesting 1,000 at a time until a call comes back short. Two things make this worse than it sounds: paging deep on a multi-dimension query gets slow enough to hit the quota above, and the totals you get by summing returned rows will not match the totals Search Console shows you.

That second point deserves its own sentence, because it produces more confused bug reports than anything else here. Summing rows does not give you a site total. Rows are sampled and anonymised query data is omitted, so the sum of the rows is always lower, sometimes dramatically. If you want a real total, make a second request with no dimensions at all. That ungrouped call is the only shape the API answers with a genuine figure.

The data is two to three days behind, by design

A query for "yesterday" returns nothing, and a query for the last seven days returns a window whose final days are incomplete and drag every average down. This is Google finalising its data, not a fault in your code and not something any tool can fix. Pull the end of your range back three days and compare like with like. If your dashboard has been quietly reporting a falling average position for months, this is very often the whole explanation.

Related: the API only holds 16 months. There is no parameter that reaches further, and once a day falls off the back it is gone for everyone. The only defence is to have started copying it into your own storage before you needed it, which is a thing that cannot be done retroactively at any price.

Domain properties, and why they are usually the right one

Properties come in two shapes. A URL-prefix property covers exactly one protocol and subdomain, so http://, https://, example.com and www.example.com are four separate properties with four separate sets of numbers. A domain property, written sc-domain:example.com, covers all of them at once. Unless you have a specific reason to split them, the domain property is the one to query — otherwise you are looking at a quarter of your traffic and concluding things about all of it.

When to write this yourself, and when not to

Write it yourself if you need something a connector will not give you: bulk URL inspection, sitemap submission, writing your own warehouse, or anything on a schedule. The API is genuinely fine once the walls above are behind you, and a first-party integration has a shorter trust chain than any third party including us.

Do not write it if what you actually wanted was to ask questions about your own search traffic. That is the case a hosted connector covers: you approve a consent screen, and the paging, the lag, the ungrouped totals and the property shapes are somebody else's problem. Mevnix is one of those, it is read-only, and it is free for one property — and because it keeps its own daily copy of your Search Console data, it is not bounded by the 16 months above once it has been running a while.

The deciding question is not features. It is whether this page reads like a list of things you already know, or like an afternoon you would rather not spend.

Mevnix connects Search Console, GA4 and Meta Ads to Claude. See what it connects, or what it costs.