Search Console API の 50,000 行制限で、あなたのデータは黙って欠けている
Search Analytics API は、1日・1サイト・1検索タイプあたり最大 50,000 行しか返しません。上限に達してもエラーは出ず、上位から返して残りを切り捨てます。 自社で運用している 13 サイトのうち 1 サイトで 180 日分の取得を検証したところ、21,323 行(+42.6%)が黙って欠けていました。この記事は、その実測と、検知・分割・再集計の手順をまとめたものです。
1. 何が起きるのか
Search Console の画面には 1,000 行までしか出ませんが、API を使えば 1 リクエストあたり最大 25,000 行、ページングで 50,000 行まで取れます。ここまでは多くの記事に書かれています。問題は、その先です。
- 上限は「1日・1サイト・1検索タイプあたり」。期間が 28 日でも 180 日でも、返る行数の上限は同じ 50,000 行です。
- 上限に達しても API は 200 OK を返す。
rowsが 50,000 件でぴったり止まるだけで、「まだある」という印は付きません。 - 切り捨てられるのは下位のクエリ。クリック 0〜1 のロングテールから消えるため、合計クリック数はほとんど変わりません。だから気づきにくい。
結果として、期間を長くするほど「クエリ数が減った」ように見えます。実際には減っておらず、取り切れていないだけです。この状態で前月と比較して「ロングテールが縮小した」と報告すると、誤った分析になります。
2. 実測:180 日で 21,323 行が消えていた
onet.co.jp(クライアントサイト、月間クリック約 4 万)で、2026 年 2 月 12 日〜8 月 10 日の 180 日間をクエリ次元で取得しました。
| 取得方法 | 行数 | 上限判定 | 合計クリック |
|---|---|---|---|
| 180 日を 1 回で取得 | 50,000 | 到達(ちょうど上限) | 259,318 |
| 45 日 × 4 回に分割して合算 | 71,323 | なし | 259,318 |
差の 21,323 行(+42.6%)が、1 回取得では欠けていた行です。合計クリックが一致しているのは、回復したのがクリック 0 の下位クエリだからで、分割で二重計上が起きていないことの証拠でもあります。
28 日の通常運用では、このサイトでも 40,000 行前後で上限に届きません。届くのは「90 日以上の効果測定」「年間比較」「複数サイトを一括で長期取得」のような場面です。つまり、いちばん慎重に扱うべき分析ほど欠けやすい構造になっています。
3. 検知する:行数を見るしかない
API はフラグを返さないので、取得側で行数を数えます。私たちは 2 段階で扱っています。
| 水準 | 条件 | 扱い |
|---|---|---|
| 上限に近い(near) | 取得行数が 40,000 行超(上限の 80%) | 下位が欠け始めている可能性。下位の増減を論じるなら期間を短くして再取得 |
| 上限到達(hit) | 取得行数が 50,000 行 | 下位は確実に欠落。「減った」「無くなった」と結論しない。期間を分割して取り直す |
80% の早期警告を入れているのは、「50,000 ちょうどでなければ安全」とは言えないからです。上限付近では既に取り切れていない可能性があり、そこから先の増減は信用できません。
4. 分割する:上限は「1 日あたり」なので期間を刻めば拾える
上限が 1 日単位で数えられる以上、期間を短く区切って複数回取得すれば、1 回では切り捨てられていた下位を拾えます。私たちの取得スクリプトは次の順で自動的に行います。
- まず期間全体で 1 回取得する
- 行数が上限(または 80%)に達していたら、期間を 2 → 4 → 7 分割の順に細かくして取り直す
- 危険域を脱した時点で採用する(分割数は最大 7 で有界。無限に細かくはしない)
ただし限界もあります。1 日単位で 50,000 行を超える巨大サイトは、日次まで分割しても取り切れません。その規模なら Search Console の BigQuery 一括エクスポート(匿名化クエリを除き行数制限の影響を受けない)が適切です。比較は BigQuery との比較 にまとめています。
5. 再集計する:掲載順位は単純平均してはいけない
分割して取った結果を合算するとき、クリックと表示回数は足すだけですが、掲載順位は足せません。表示回数 10 のクエリと 10,000 のクエリを同じ重みで平均すると、数値が狂います。
順位 = Σ(順位 × 表示回数) ÷ Σ(表示回数)
この式は、分割取得の合算だけでなく、複数クエリ・複数ページ・複数期間をまとめるときすべてに当てはまります。SQL で AVG(position) と書いた瞬間に誤りになるので、私たちはビュー側にこの式を固定し、生の列名を position_raw にして素朴な平均が目立つようにしています。
検証として、bulkfit24.com で分割を強制発火させ、分割前後でクリック 193・表示 11,705 が完全に一致し、順位の再集計が数値を歪めないことを確認しています。
6. 運用ルール:3 つだけ
- 行数を必ず記録する。取得したデータには「上限に達した状態で取られたか」を一緒に保存する。後から見た人が判断を誤らないために。
- 欠落リスクがある状態で「減った」と結論しない。報告書に書くなら「取得上限の影響を受けている可能性」を併記する。
- 過去の取得結果と行数を比べない。分割を導入した後は、同じ期間でも行数が増える。データが増えたのではなく、欠落が減っただけ。
7. 自分で確かめる方法
手元のスクリプトや Looker Studio の取得で、返ってきた行数が 25,000 の倍数(特に 50,000)でぴったり止まっていたら、まず疑ってください。期間を半分にして 2 回取り、行数の合計が 1 回のときより増えるなら、欠けていた証拠です。
このダッシュボードは、上の検知・分割・再集計を毎週の自動取得に組み込み、各データに欠落リスクを付けて保存しています。仕組みの詳細は データの正しさ、指標の計算式は 指標の定義 を参照してください。
参考
- Google 公式: Search Console API の取得制限(1 日・サイト・検索タイプあたり 50,000 行)— developers.google.com/webmaster-tools/limits
- Google 公式: 検索パフォーマンスデータの詳細(匿名化クエリ、集計方法)— developers.google.com/search/blog/2022/10/performance-data-deep-dive
- Google 公式: BigQuery 一括エクスポート — support.google.com/webmasters/answer/12917675