There is no simple API key for the Search Console API. You sign in with OAuth or with a service account, and the JSON file that Google Cloud gives you is the "key" that most tutorials refer to.
For automated reports, use a service account. This guide covers how to create one, how to give it access to your property, which errors you will see and what causes them, which quotas apply and how to get more than 25,000 rows from a single report.
You may only want Search Console data so you can decide which articles to write. In that case you don't need a script. SEO automation finds the real Google searches for your market and plans one article for each intent. Start for $1 and get your SEO plan in a few minutes.
Is there a Google Search Console API key?
No. Some Google APIs accept a plain key, but Search Console data is private, so every call has to be authorized for a user who has access to the property. The official overview says you need owner, full or restricted access to the property you query. There are two ways to authorize:
| OAuth client (desktop or web) | Service account | |
|---|---|---|
| Who signs in | A human, in a browser, once | Nobody, it is a robot identity |
| File you download | Client ID and secret JSON | Private key JSON |
| Token handling | You store and refresh a token | The library handles it |
| Best for | Local scripts, tools that act for users | Cron jobs, CI, n8n, scheduled reports |
| Access to the property | Your own access | Added as a user in Search Console |
If the job runs without anyone at the keyboard, use a service account.
How to get the Google Search Console API key JSON file
- Open the Google Cloud console and create a project, or pick an existing one.
- Go to APIs and Services, search for "Google Search Console API" and click Enable.
- Under IAM and Admin, open Service Accounts and create one. It does not need any Cloud roles to read Search Console.
- Open the account, go to Keys, choose Add key, then JSON. The file downloads once. Store it safely.
- Copy the
client_emailvalue from the JSON file. - In Search Console, open the property, then Settings, Users and permissions, Add user. Paste the email and pick a permission level.
People often skip steps 5 and 6, and that is where most "it doesn't work" problems come from. The o7planning walkthrough follows the same order.
Then choose the narrowest scope that does the job. Use webmasters.readonly for reports. Use webmasters only if the script also submits sitemaps (scopes reference).
The siteUrl trap
The siteUrl value must match the property exactly. A domain property is written sc-domain:example.com. A URL prefix property is the full URL with its trailing slash, like https://www.example.com/. If the format is wrong, the call fails even when the permissions are correct.
Search Console API errors: what they mean and how to fix them
Every Google API returns an HTTP code and a short reason. Google lists them on its API error reference. These four cover almost every failed first call.
| HTTP code and reason | Google's description | Most likely cause | Fix |
|---|---|---|---|
403 insufficientPermissions |
"The authenticated user does not have sufficient permissions" | The service account email was never added to this property | Add client_email in Users and permissions |
| 403 on a property you did add | Permission denied | siteUrl points to another property (domain vs URL prefix, www vs no www, http vs https) |
Use the exact format returned by sites.list |
403 accessNotConfigured |
"Your project is not configured to access this API" | The API is enabled in another Cloud project, not the one that owns the key | Enable the Search Console API in the key's own project |
429 rateLimitExceeded |
"Too many requests have been sent within a given time span" | Too many calls per minute, or heavy queries that use up the load quota | Slow down and retry with a growing delay |
403: the user does not have sufficient permission for the site
Google's error reference describes insufficientPermissions as a call made by an identity that lacks the rights it needs. In Search Console, permissions live on the property and not in Google Cloud. A service account with Owner rights on the Cloud project still has no access to your data until its email appears in Settings, Users and permissions. A developer who debugged this exact case arrived at the same conclusion: Cloud IAM roles alone don't grant access to Search Console.
Site not in your list: the wrong siteUrl format
If the email is on the property and you still get a 403, check the format. The same write-up shows a 403 PERMISSION_DENIED that came from sending sc-domain: for a property registered as a URL prefix. Search Console treats those as two separate properties.
The fastest check is to ask the API itself. sites.list returns the Search Console sites the authenticated account can see, with their permission level. Copy the siteUrl from that response instead of typing it.
for s in gsc.sites().list().execute().get("siteEntry", []):
print(s["siteUrl"], s["permissionLevel"])
If the list is empty, the account has no access yet. If your site appears in another format, use that format.
403 accessNotConfigured: the API is off in this project
Google's error reference gives the message "Your project is not configured to access this API. Please use the Google Developers Console to activate the API." This happens when you enable the API in one Cloud project and create the key in another. Open the project that owns the service account, then check APIs and Services.
429: too many requests
The error reference lists rateLimitExceeded under 429. The usage limits page also says that every quota overrun returns a "quota exceeded" error. For the short term load quota, Google says to wait 15 minutes and try again. If the error comes back, you are exceeding the long term quota. In that case, make the queries lighter: group by page or query less often, use shorter date ranges and stop requesting the same data twice.
In a script, retry with a growing delay rather than a tight loop:
import time
from googleapiclient.errors import HttpError
def run(request, tries=5):
delay = 10
for attempt in range(tries):
try:
return request.execute()
except HttpError as e:
if e.resp.status not in (429, 500, 503) or attempt == tries - 1:
raise
time.sleep(delay)
delay *= 2
API limits and quotas you will actually hit
Figures from Google's usage limits page:
| Resource | Per site | Per project |
|---|---|---|
| Search Analytics | 1,200 queries/min (also 1,200/min per user) | 40,000/min, 30,000,000/day |
| URL Inspection | 600/min, 2,000/day | 15,000/min, 10,000,000/day |
| Sitemaps, Sites | 20/s and 200/min per user | 100,000,000/day |
For reports, the number of queries is rarely what stops you. Google also applies a load quota, measured over 10 minutes and over one day. Requests that group by both page and query over long date ranges use it up fastest. For URL Inspection, the daily cap per site is the real limit, so inspect your most important URLs first.
Quotas, retries and siteUrl formats are a lot of upkeep if all you need is a list of articles to write. With SEO Automation, there is no key, no cron and no script to maintain. Start for $1 and get your SEO plan in a few minutes.
Pull every row, not the first 1,000
The query method returns 1,000 rows by default and 25,000 at most per call. To get more, page through the results with startRow. You can group by query, page, country, device, date, hour and searchAppearance.
import os
from google.oauth2 import service_account
from googleapiclient.discovery import build
creds = service_account.Credentials.from_service_account_file(
os.environ["GSC_KEY_FILE"],
scopes=["https://www.googleapis.com/auth/webmasters.readonly"])
gsc = build("searchconsole", "v1", credentials=creds)
def all_rows(site, start, end, dims=("query", "page")):
rows, start_row = [], 0
while True:
body = {"startDate": start, "endDate": end, "dimensions": list(dims),
"rowLimit": 25000, "startRow": start_row}
batch = run(gsc.searchanalytics().query(
siteUrl=site, body=body)).get("rows", [])
rows += batch
if len(batch) < 25000:
return rows
start_row += 25000
rows = all_rows("sc-domain:example.com", "2026-08-01", "2026-10-31")
Run it on a schedule with cron or GitHub Actions. Then write the rows to a sheet or warehouse, or send them to a dashboard.
Keep the JSON file safe
- Never commit it. Add it to
.gitignoreand point to it with an environment variable. - In CI, store its contents as a secret and write it to a temporary file at run time.
- Give the service account restricted access if it only reads data.
- Rotate the key: create a new one, deploy it, then delete the old one in Google Cloud.
What to automate, and what stays human
Scripts can handle the repetitive work: pulling data every week, spotting pages that slip from page 1 to page 2, flagging titles with high impressions and few clicks, and submitting sitemaps.
People still need to decide what a drop means, which pages are worth updating and whether a new title still describes the page honestly. Keep a person on that review step.
Plan articles from real searches without writing a script
If you only wanted the API to decide what to publish, SEO Automation does that job with no setup on your side. You don't need a key, a service account or a cron job, and there is nothing to maintain when a quota changes.
- Scout reads your site and finds the real Google searches for your market.
- Strategist plans one article per search intent, easiest wins first.
- Writer researches on the web and writes with sources.
- Editor checks every fact and every link before anything goes live.
- Publisher publishes on WordPress, Shopify, Webflow, Wix, Framer, GitHub or by webhook. It then sends the sitemap to Google through Search Console and notifies Bing through IndexNow.
Articles stuck on page 2 are updated, and titles with a low CTR are rewritten. You still read what goes out, because no tool should publish to your site without a human check. There is also a Claude connector. See the pricing page for what the plan includes.
Frequently asked questions
How do I get a Google Search Console API key?
There is no classic key. Create a service account in Google Cloud, download its JSON key and add its client_email as a user on your Search Console property. That JSON file is your credential.
Why does the Search Console API return 403?
Google's error reference lists several 403 reasons. In practice, the three common causes are: the service account was not added to the property (insufficientPermissions), siteUrl does not match the property format, or the API is not enabled in the key's Cloud project (accessNotConfigured).
How many rows can one request return?
Up to 25,000. The default is 1,000. Use startRow to fetch the next block until a call returns fewer rows than your limit.
Service account or OAuth for automation?
Use a service account for anything scheduled or headless. Use OAuth when a person signs in and the tool acts on their behalf.
Start for $1 and get your SEO plan in a few minutes.