Ask Search Console for one day of keywords and it stops at 5,000
Ask Google's Search Console API how many different search terms your site appeared for on a single day, and once the true answer goes past 5,000 you stop getting the true answer. The request succeeds, the response looks complete, and nothing in it says rows were withheld. We found it the ordinary way: we plotted daily keyword counts for a connected property while building our sync, and the line stopped moving at a suspiciously round number.
The short version
A single-day request for the query dimension returns at most 5,000 rows. There is no error, no warning field and no marker on the last row, so a daily "how many searches did we appear for" counter plots that ceiling as if it were a measurement, flat at exactly 5,000 while impressions and clicks keep climbing. Clicks and impressions per day are unaffected; anything that counts keyword rows per day is. On a property big enough to have more than 5,000 different search terms in a day you can reproduce it in the API Explorer in about a minute (below that the ceiling never comes into play), and the honest response is to store such a day as a floor rather than a total.
The line goes flat at a suspiciously round number
On the busiest days the count is exactly 5,000, day after day. The quieter days still move.
4,987, then 5,014, then 4,996: close to 5,000, and crossing it both ways.
The chart above is the one that starts this. For each day, count the distinct queries your site appeared for: how many different search terms produced at least one impression, meaning at least one time a link to your site was shown in Google's results. Plot that per day.
On a small site the line wanders around and looks like data. On a site that is growing, it climbs, and then one day it stops. It does not taper off; it stops. It sits at 5,000. The next day is 5,000. The busiest day of the year is 5,000.
Everything around it keeps behaving normally, which is what makes it hard to catch:
- Impressions and clicks for the same days keep rising.
- Average position, the mean rank of your results across those impressions, keeps moving.
- The days below the ceiling look completely natural. They scatter the way counts do, with no bunching just underneath the line and no gap in front of it.
- The days sitting on the ceiling are your biggest days, and more of them join as the site grows. A day hits the lid when it genuinely has more than 5,000 different search terms in it, which is not quite the same thing as being the busiest day by impressions, but in practice tracks it closely.
That combination is the signature. A real count does not land on the same round integer day after day, and it certainly does not do so only at the top of the range. A distribution that rises smoothly and is then sliced flat across the top is not a distribution. It is a distribution with a lid on it. What is being plotted on those days is not how many searches you appeared for. It is how many rows Google was willing to hand over.
Why it happens
The ceiling belongs to one specific request shape. Call searchanalytics.query with startDate and endDate set to the same day and dimensions: ["query"], and ask for the documented maximum of rowLimit: 25000. On a day that genuinely has more, you get 5,000 rows back. That was still the behaviour when we last checked it, on 4 September 2026.
What you do not get:
- An error. It is a normal
200. - A truncation flag. The response body carries the
rowsarray andresponseAggregationType, and that field describes how impressions were aggregated, not whether anything was withheld. - A partial-page hint. Nothing on the 5,000th row distinguishes it from a genuine last row.
Ask for the next page, the same request with startRow: 5000, and the response comes back with no rows at all. Not row 5,001: nothing. As far as the API is concerned, that day is finished.
Now change one thing. Keep dimensions: ["query"] and widen the range to the same week or month. That request pages far past 5,000 quite happily. So the ceiling is not your quota, not your property and not the page size. It is a property of asking about a single day on the query dimension. We have not tested a single day on the page dimension, because nothing we build asks for one: our page pulls are all multi-day, and those page far past 5,000 as well. Treat the ceiling as established for single-day [query] and unmeasured everywhere else.
Google does not document why, and we are not going to invent a reason. What we can say is that the behaviour is exact and repeatable, and that rows arrive ordered by clicks descending. Past the first few hundred rows almost nothing has any clicks at all, and Google does not publish how it breaks those ties. So the 5,000 you keep are the top of a list whose ordering below the clicked rows is undocumented, and what falls off comes from the low-volume tail. That tail is precisely the part people build these dashboards to find.
Telling a ceiling apart from a real plateau
Sites do plateau. Traffic flattens, a seasonal peak ends, a category stops growing. So the question is not "is my line flat", it is "is my line flat because nothing changed, or because something stopped counting". Four checks, in the order they are worth doing:
Is the number exact and repeated?
Real counts wobble. 4,987 then 5,014 then 4,996 is a plateau. 5,000 then 5,000 then 5,000 is a lid. Approaching 5,000 is a busy site. Sitting on 5,000 is the API.
Which days are flat?
If the flat days are your best days by impressions, and the quieter days move freely, that is a ceiling. A genuine plateau does not care how busy the day was.
Ask for the second page.
Re-run the day with
startRow: 5000. An empty response on a day you believe has more is the cheapest confirmation available.Compare the sum of days against the same range asked as one request.
This is the rigorous one. Distinct queries over a month can never be more than the per-day counts added together, and are usually far fewer, because most queries recur on several days. So if the month asked as a single request comes back with more distinct queries than the days add up to, something is missing from the days. Truncation is the usual cause. The other one is Google's privacy threshold, which is applied over whatever range you ask about: a query with a single impression on each of twelve days can be withheld from every one of those days and still be named in the month. Either way, the per-day counts are a floor, which is the point.
Checks 1 and 4 are also worth running on any tool that shows you a keyword count per day, including ours. If a number cannot survive being asked for twice in two different shapes, it should not be on a chart.
What it breaks downstream
The damage is narrow but it lands in the places people trust most. Anything derived from a daily count of keyword rows inherits the ceiling:
Growth curves.
"Search terms we appear for" flattens exactly when the site outgrows the API, so the chart shows a plateau at the moment the site is doing best.
Period comparisons.
If your busy period is capped and your quiet one is not, growth is understated, and a site that grew can be shown declining, because only one side of the comparison had its tail removed.
"New keywords this period" counts.
A query missing from a capped day may have been served and simply not reported, so a capped range never gives you the full list of entrants. It is not a clean undercount either: a search that merely crossed an impression threshold also lands in "first reported", so the number is short in one direction and padded in the other. That is a figure to label, not to print as a total.
Long-tail share.
The rows removed are the low-volume ones, so a "share of traffic from long-tail searches" figure is computed on a numerator that was cut precisely where it mattered.
Looker Studio.
A dashboard on Google's Search Console connector, with Date as the dimension and a distinct count of Query, is asking Search Console the same question. We cannot see the request the connector actually sends, so if your chart shows a flat top on the busiest days, check those days against the API directly before you explain the plateau to a client. The same applies to Sheets add-ons and any script that loops over days calling
searchanalytics.query. The BigQuery bulk export is a different pipeline and carries no such ceiling; its limitation is a different one, that it only records forward from the day you switch it on (checked 4 September 2026).
What is not affected: daily clicks, impressions, CTR (the share of impressions that became clicks) and average position for the site as a whole. Those come from a request with no query dimension, a handful of rows, and the ceiling never touches them. Site-level trends are fine. Keyword-level counts are the ones to distrust.
What we do about it, and where we still cannot know
We pull raw rows into our own tables, so first we had to decide how to ask.
One day per request.
Never a month by default. A multi-day
[date, query]request orders rows by clicks across the whole range and cuts once, so some days come back a fraction full, and which ones cannot be predicted from outside the request (we measured it in the row-ordering post). That is invisible truncation, and considerably worse than the cap itself, because every day still has some rows in it. We merge a month into a single request only when the per-day counts we already hold add up well under the page size, with any day we have not counted yet charged at the busiest day we have, and with no day in that month sitting at the ceiling. "Well under" is deliberately below the page size, because the counts feeding that sum may themselves be capped undercounts. It is an estimate built to err towards splitting, not a proof.We page past the ceiling on the days that reach it.
A day that comes back at exactly 5,000 gets a follow-up request; a day that comes back below it is genuinely exhausted and costs nothing extra. The empty response to that follow-up is what turns an assumption into a measurement.
We store the day as capped, not merely as a count.
A day pinned to exactly 5,000 is written with a flag beside it, and where the app compares two periods it says so in plain words, for example: "3 of these days hit Google's own limit of 5,000 keywords a day, so the long tail of those days was never reported to anyone. The counts below are a floor, not a total."
What we cannot do. We cannot tell you the true number of search terms on a capped day. Nobody can: those rows were never served to anyone, and we do not estimate, extrapolate or model them, because a modelled number on this chart would be indistinguishable from a measured one, which is the whole problem we are describing. So on capped days our keyword count is a floor, our "first reported this period" count is a floor, and we label them as floors instead of printing something confident.
Two further honesty notes. For privacy reasons Google withholds rare queries from everything it publishes: the interface, the API and the bulk export alike. So even an uncapped day is not the complete truth. And Search Console data lags two to three days for everyone, including us. Nothing changes that.