Google Search Console CLI
- Agents and operations
- Operations CLI
- 2026
- Open source
Go, Search Console API, OAuth 2.0 with PKCE, OS keychain
Google Search Console CLI is a Go binary called gsc for search performance, URL inspection, sitemaps and properties. It implements all ten active methods of the Search Console API. On top of them it adds what the web interface lacks: period comparisons, a resumable day by day export, and opportunities computed locally. I built it for a person at a terminal and for a coding agent that needs stable JSON.
The web interface answers one question at a time and caps its tables at a thousand rows. The questions I actually ask are joins. Which queries sit just off page one, which pages compete for the same query, which queries vanished since last month. Each answer meant a spreadsheet export and arithmetic by hand, and an agent can do neither through a browser.

# parsed with the real command tree, never rungsc commands resolve -- auth token{ "command": "gsc auth token", "effect": "read", "conditional": false, "interactive": false, "secret_output": true, "flags": {}, "args": []}
1 command9 lines of output
- Chapter
- Agents and operations
- Category
- Operations CLI
- Year
- Availability
- Open source
- Last commit
- Go
- Search Console API
- OAuth 2.0 with PKCE
- OS keychain
Signing in once
Search Console data belongs to a Google account, so every request needs an OAuth token. API keys do not work, and Google’s device-code flow excludes the Search Console scopes. gsc auth login listens on a free port on 127.0.0.1 and opens the consent page with PKCE and a random state. The refresh token goes into the OS keychain. Release binaries carry a Desktop OAuth client injected through -ldflags, so a first login needs no Google Cloud project. Service accounts, Application Default Credentials and impersonation cover CI. Without a keychain, login stops and offers --insecure-storage rather than writing plaintext quietly. Nothing falls back to ambient credentials on its own, so an agent never runs as an identity nobody chose.
Reading the numbers
Most of the code exists so the numbers are not misread. Dates are Pacific Time and inclusive, and --last 28d ends at the latest day with data, found by one small probe. Rows arrive in pages of up to 25,000, and complete: true means pagination ended, never that every query was seen. Google withholds anonymized queries, so totals come from gsc performance, not from summed query rows. --compare previous or yoy runs a second query and joins the two. A row missing from one period is null, not zero, and CTR changes are in percentage points. trend --by month sums clicks and impressions, recomputes CTR from the sums and weights position by impressions.
Safety by effect
Each command is classified by what it does, not by its HTTP verb. Search Analytics and URL Inspection are POST requests, yet both only read and run under --read-only. sites remove and sitemaps delete are remote writes, export is a local write, and auth token is refused under --read-only because it prints a credential. GSC_READ_ONLY=1 in the environment cannot be undone by --read-only=false later. TestAgentSafetyCommandManifest hashes every command with its annotations, so reclassifying one is a deliberate change. gsc commands resolve parses arguments with the real command tree and reports their effect without running them. Reckon calls it before each run and refuses anything that is not a plain read.
Choices and their cost
- I call the REST endpoints directly, not through the generated
searchconsole/v1Go client. Ten methods did not justify its dependency graph. The cost is upkeep.TestAPICoveragechecks a vendored discovery snapshot and fails for every method a refresh adds, removes or changes. - The built-in OAuth client ships inside release binaries, which is what makes login one command. Everyone on it shares one project’s quota, and source builds have no client at all.
- Nothing retries automatically except
export --retry N. Search Analytics has unpublished load quotas, and a retry loop is how an agent burns them. A transient failure stops the command instead. - Logins default to the full
webmastersscope, with--scope readonlyas the option. This is the one I would revisit. A read-only default would put the guard against a straysitemaps deletein Google’s token, not only in my flag.
A weekly search review
gsc auth login
gsc freshness
gsc performance --last 28d --compare previous -o json
gsc insights striking-distance --last 28d --min-impressions 200
gsc insights cannibalization --last 3m -o json
gsc export --last 16m -d query -d page --out ./gsc-export
freshness comes first, because final data usually lags two to three days. Each insight prints its thresholds, and striking-distance defaults to positions 4 to 20. The export writes one CSV per day through a temporary file and a rename, and manifest.json records finished days. Rerunning resumes, preliminary days are fetched again, and a changed request needs --restart.
Where it stops
It is an independent client, not affiliated with Google, and it reports only what the API exposes. Core Web Vitals, Page indexing, manual actions, links and live URL tests are absent. So are the AI Overviews and AI Mode reports, whose traffic sits inside ordinary totals. gsc inspect shows the indexed version only, and stops cleanly at the quota of 2,000 inspections per property per day. The name collides with Ghostscript and Gambit Scheme, so the installer and gsc doctor warn. It is MIT licensed, at v0.1.8, and updates itself on macOS, Linux and Windows. Bing gets the same treatment in Bing Webmaster CLI.