Bulk SERP API

Googleデータを大規模に収集するBulk SERP API

100万件のGoogle検索を数分でキューに登録し、収集はSemscraperにお任せください。1回のAPIリクエストで最大1,000キーワード、非同期処理、署名付きコールバックに対応し、結果の取得はすべて無料です。

  • 1回のリクエストで1,000キーワード
  • 署名付きコールバックで非同期処理
  • 10万SERPあたり約€30
  • 1,000件の無料SERP
  • クレジットカードなし

100万件のGoogle検索を数分でキューに登録

1回のAPIリクエストで最大1,000キーワード、1分あたり最大500リクエストを送信でき、前のバッチの完了を待つ必要はありません。リクエストはすぐにキューに登録され、処理能力に空きが出しだい順次処理されます。ただし、送信できる量と処理速度は別物です。実際の完了時間はキューの混雑状況と利用可能な処理能力によって変わります。処理能力は需要の増加に合わせて拡張しています。

1. 送信

1,000キーワード単位のバッチを、必要なだけ送信できます。キーワードごとに国、言語、都市、デバイス、取得ページ数を個別に指定できます。

2. 収集

すべてのSERPを実際のブラウザでレンダリングします。アカウントごとに専用のキューがあり、各アカウントを順番に処理します。自分のリクエスト同士の順序は1〜10の優先度で調整できます。

3. 受信

各結果は準備ができしだいコールバックURLにPOSTされます。完了した結果を好きなタイミングでまとめて取得することもできます。

本番環境の処理量に対応

1日に数万件の検索を実行するチームが、本当に必要とする機能を揃えています。

署名付きコールバック

すべてのコールバックには、本文のHMAC SHA-256署名がX-Signatureヘッダーに付与されます。署名にはAPIキーのメニューに表示されるキーを使います。

確実なリカバリー、無料の取得

まだ取得していない完了済みの結果は保持され、1回のリクエストで一覧を取得できます。結果の取得は無料で、何度でも実行できます。課金されるのは検索の作成時のみです。

SERP全体を最大10ページまで

順位とピクセル位置付きの自然検索結果、AI Overviews、広告、ローカルパックなど、すべてのブロックをJSONまたはHTMLで取得できます。一覧はGoogle検索APIをご覧ください。

大規模利用の料金

SERP単位の従量課金で、サブスクリプションはありません。残高に有効期限はありません。

SERP数1ページ目(約10件)10ページ(約100件)
10,000€3.00€21.00
100,000€30.00€210.00
1,000,000€300.00€2,100.00

標準料金です。チャージ時の1〜10%割引は含みません。Googleが返すページ数が指定より少ない場合、課金は取得できたページのみです。料金の詳細。

動作確認済みのサンプルコード

Python:キーワードリストをキューに登録し、コールバックを検証したうえで、サーバーが受け取り損ねた結果を回収します。2026年10月9日に本番APIで実行し、有効な署名付きのコールバックを受信、回収ループは2回目の実行で残りゼロ、取得による課金もありませんでした。この例は英語版のGoogle.comが対象です。Google日本の結果を取得するには、location「jp」とlanguage「ja」を指定してください。

1. bulk.py:すべてのキーワードをキューに登録
# bulk.py  -  python bulk.py queue keywords.txt   then later   python bulk.py catch-up
import json, sys, time
import requests

API = "https://api.semscraper.com/v1/serp"
HEADERS = {"Authorization": "Bearer API_KEY"}
CALLBACK = "https://your-server.com/serp-callback"  # or None: catch-up only

def save(serp, path="serps.jsonl"):
    with open(path, "a", encoding="utf-8") as f:
        f.write(json.dumps(serp, ensure_ascii=False) + "\n")

def queue(keywords):
    for i in range(0, len(keywords), 1000):  # 1,000 keywords per call
        batch = [{
            "search_engine": "google_search",
            "keyword": kw,  # a keyword must not contain a comma
            "device": "desktop",
            "location": "en",
            "language": "en",
            "depth": 1,
            **({"callback_url": CALLBACK} if CALLBACK else {}),
        } for kw in keywords[i:i + 1000]]
        for attempt in range(6):
            r = requests.post(API, json=batch, headers=HEADERS, timeout=60)
            if r.status_code != 429:  # 429: over 500 calls/minute, nothing was queued
                break
            time.sleep(10 * (attempt + 1))
        r.raise_for_status()
        print(r.json()["count"], "keywords queued")
2. callback_server.py:各コールバックを受信して検証(Flask)
# callback_server.py  -  flask --app callback_server run
import hashlib, hmac, json
from flask import Flask, request

SECRET = b"hmac_..."  # HMAC key from your API keys menu
app = Flask(__name__)

def save(serp, path="serps.jsonl"):
    with open(path, "a", encoding="utf-8") as f:
        f.write(json.dumps(serp, ensure_ascii=False) + "\n")

@app.post("/serp-callback")
def serp_callback():
    raw = request.get_data()
    expected = hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, request.headers.get("X-Signature", "")):
        return "Invalid signature", 401
    for serp in json.loads(raw):  # a list holding the finished SERP
        save(serp)
    return {"status": "ok"}       # anything but 200 leaves it unfetched
3. bulk.py(続き):受け取り損ねた結果を回収
# bulk.py, continued: finished results that were never fetched
def catch_up():
    while True:
        r = requests.get(API, headers=HEADERS, timeout=60)  # up to 1,000 per call
        r.raise_for_status()
        ids = [p["id"] for p in r.json().get("data", [])]
        if not ids:
            break
        for i in range(0, len(ids), 100):
            r = requests.get(API, headers=HEADERS, timeout=60,
                             params={"ids": ",".join(ids[i:i + 100]), "output": "json"})
            r.raise_for_status()
            for serp in r.json()["data"]:
                save(serp)  # fetching marks it as fetched, and is never billed

if __name__ == "__main__":
    if sys.argv[1] == "queue":
        queue(open(sys.argv[2], encoding="utf-8").read().splitlines())
    else:
        catch_up()

958,176件のSERPで実測

私たちのAI Overviews調査では、デスクトップとモバイルで合計215万件以上のSERPを収集しました。そのうちの1回では、2026年9月12日に100万件近いフランス語キーワードをキューに登録しました。958,176件のSERPすべてを、最初のリクエストから4時間23分以内にエラーゼロで収集・取得しています。最も処理が多かった1時間では237,043件のSERPを返しました。これは自社アカウントでの実際の収集結果であり、処理速度を保証するものではありません。完了時間は取得ページ数、待機中のリクエスト数、利用可能な処理能力によって変わります。

958,176

件の1ページSERPをエラーゼロで収集・取得。

4時間23分

最初のリクエストから最後の結果まで。

237,043

件のSERPを、最も処理が多かった1時間で取得。

事前に知っておきたいこと

項目仕組み
SERP 1件とバッチ全体SERP 1件の処理時間は、実際のブラウザでレンダリングするため中央値で約30秒、10ページなら約1分です。多数のロボットが並行して動くため、バッチは順次処理され、各SERPの処理時間の合計よりはるかに早く完了します。
処理能力ロボットの台数は需要に合わせて増やしており、処理量の増加に応じて処理能力を追加しています。非常に大量の処理を定期的に予定している場合は、事前にご連絡いただければ必要な規模を用意します。
コールバックの配信各結果のPOSTは1回のみです。エンドポイントがHTTP 200を返さなかった場合、その結果は未取得のまま残り、回収ループで取得できます。
IDによる取得1回のリクエストで最大100件のIDを指定できます。大量の場合は、コールバックか、完了済み・未取得の結果一覧(1回あたり最大1,000件)をご利用ください。
リアルタイム性大規模な収集向けの設計であり、チャットボットの即時応答には向いていません。AI向けのデータセットやエージェントにはAI向けSERP APIをご覧ください。
FAQ

よくある質問

一度に何件のキーワードを送信できますか?
1回のリクエストで最大1,000件、1分あたり最大500リクエストです。前のバッチの完了を待たずに次のバッチを送信できます。すべてすぐにキューに登録され、順次処理されます。
コールバック用のエンドポイントが停止していた場合はどうなりますか?
結果が失われることはありません。HTTP 200を受け取れなかったコールバックの結果は、未取得のまま残ります。IDを指定せずにGET /v1/serpを呼び出すと、完了済み・未取得の結果を最大1,000件まで一覧でき、そのIDで結果を取得できます。取得に課金されることはありません。
コールバックがSemscraperから送られたものか、どう確認すればよいですか?
APIキーのメニューに表示されるHMACキー(hmac_で始まります)を使って、リクエストの生の本文からHMAC SHA-256を計算し、定数時間比較でX-Signatureヘッダーと照合してください。
1つのバッチで国、デバイス、取得ページ数を混在させられますか?
はい。バッチ内の各項目に、location、言語、geolocation、デバイス、取得ページ数、優先度を個別に指定できます。ただし、キーワードにカンマを含めることはできません。2つの検索に分割されてしまいます。
10万件のSERPにはどのくらい時間がかかりますか?
処理時間は保証していません。取得ページ数と、送信時のキューの混雑状況によって変わります。参考までに、自社で実行した958,176件の1ページSERPは4時間23分で完了しました。インフラは需要に合わせて拡張しています。非常に大量の処理を定期的に行う場合は、事前にご連絡いただければ必要な処理能力を追加します。

お手持ちのキーワードリストで始めましょう

1,000 SERPまで無料、クレジットカード登録は不要です。