Blog · Search Console

A Google Search Console API alternative, for people who just want the data

Published July 24, 2026 · 9 min read

Most people looking for a Search Console API alternative don't actually want a different API. They want to skip the four things every GSC client ends up building. The API works fine — it's well documented and it does what it says. The cost is that "get my Search Console data into something I can query" turns into an auth layer, a pagination loop, a storage schema and a scheduler, none of which are the thing you set out to do. This post is an honest map: what the API costs you, what each alternative trades away, and how to get from zero to a SQL query over your own GSC data.

The four things you end up building anyway

Write a Search Console client and the shape is always the same, regardless of language:

  1. Auth. OAuth 2.0, a consent screen, and then the unglamorous part — storing a refresh token somewhere that isn't your git repo, and refreshing it before it bites you at 3am.
  2. Pagination. The Search Analytics endpoint returns a capped number of rows per request (25,000), so any query with the query or page dimension on a real site means looping with startRow until the response comes back short.
  3. Storage. The API answers one request at a time and returns JSON. Every interesting question — week over week, which queries are new, which pages decayed — is cross-day, so you have to land the rows somewhere before you can ask anything. That's a schema, a database and a dedupe strategy.
  4. A scheduler with a memory. Data finalizes late, so you can't pull once and be done; you need incremental syncs that re-pull the trailing window, plus retries for the runs that fail while you're asleep.

None of it is hard. All of it is maintenance, and it's maintenance that produces zero insight on its own. Add the API's own boundaries — data retained for about 16 months, and rare queries withheld for privacy so your row totals never quite reconcile with the summary numbers — and you've spent a weekend to arrive at the starting line.

The honest comparison

There are four realistic paths. Which one is right depends entirely on what you're building.

1. The API itself

Best when you're shipping a product on top of GSC data, need control over every field, or have compliance reasons the data can't leave your infrastructure. Costs the four layers above, forever.

2. Looker Studio's Search Console connector

Best when you need a chart for a stakeholder this afternoon and nothing else. Free, no code. Trades away the data itself — it lives inside the report, so joining it against ad spend or GA4 sessions means fighting blend limitations, and there's no SQL surface to ask an unanticipated question. Reports also tend to get slow as ranges grow.

3. The UI export

Best when it's genuinely one-off. Trades away completeness and time — the interface caps what you can pull, and every export is a snapshot that's stale tomorrow. Fine for one answer, corrosive as a habit.

4. A managed backend you query in SQL

Best when you want the data as data — queryable, joinable, current — without owning the pipeline. This is where TableBI sits: connect Search Console once, and the rows land in a table your agent (or you) query with ordinary read-only SQL. Trades away field-level control over the sync itself; you get the connector's behavior, not your own.

Not a hosted-model product: TableBI runs no LLM over your numbers. The backend serves deterministic SQL results; if an agent is doing the interpreting, that happens in your own Claude Code session under your account. Inference cost on our side is $0.

Zero to a query, without a client

The connector owns auth, pagination, incremental syncing and retries. Your side is one command:

terminal
npm i -g @tablebi/cli
tablebi login

# browser opens for OAuth, then data syncs in
tablebi connect gsc --site sc-domain:example.com

No consent screen to configure, no refresh token in your repo, no startRow loop. To keep a source current later, or to see how far behind each one is:

terminal
tablebi sync gsc          # pull the latest, with retries handled server-side
tablebi sources           # connected sources + freshness

What you actually came for: SQL over GSC

Synced Search Console data lands in search_console_raw — lossless, per-row, exactly as Google reported it: date, site, query, page, clicks, impressions, position. Which means the questions that needed a storage layer are now one command. Rising and falling queries, week over week:

terminal
tablebi ask "SELECT query,
             SUM(CASE WHEN date > (SELECT MAX(date) FROM search_console_raw) - 7
                      THEN impressions ELSE 0 END) AS this_week,
             SUM(CASE WHEN date <= (SELECT MAX(date) FROM search_console_raw) - 7
                      THEN impressions ELSE 0 END) AS prev_week
             FROM search_console_raw
             WHERE date >= (SELECT MAX(date) FROM search_console_raw) - 14
             GROUP BY query ORDER BY this_week - prev_week DESC LIMIT 20"

Pages that get impressions but no clicks — the CTR opportunity list, using the avg_position macro so position is impression-weighted rather than a naive average of averages:

terminal
tablebi ask "SELECT page, SUM(impressions) AS imp, SUM(clicks) AS clicks,
             avg_position(SUM(position*impressions), SUM(impressions)) AS pos
             FROM search_console_raw
             WHERE date >= (SELECT MAX(date) FROM search_console_raw) - 28
             GROUP BY page HAVING SUM(impressions) > 200
             ORDER BY clicks ASC LIMIT 20"

Two details worth stealing. First, anchor date windows to MAX(date), never to today — GSC finalizes performance data roughly two to three days late, so a filter on the current date silently includes days that will fill in later and makes every recent trend look like a collapse. Second, the impression-weighted position: averaging the position column directly gives a number that's wrong in a way that looks plausible, which is the worst kind of wrong.

If you run several sites, there's a shortcut for the question you'd otherwise write by hand every Monday:

terminal
tablebi scoreboard # which properties are growing, which are sliding

The thing the API can't give you: joins

This is the real argument for landing GSC data somewhere queryable rather than calling the API per question. Search Console alone tells you what happened in organic search. It can't tell you whether the page that lost impressions is one you're also paying to advertise on, or whether the traffic you kept actually converted.

Because GA4, Meta Ads and Google Ads connect through the same backend, organic sits next to paid under one set of definitions — a unified facts table with shared macros (roas, ctr, cpa) alongside the per-platform raw tables. Every answer also carries a trust block: how fresh each source is, and the caveats that stop naive comparisons — including the explicit one that a GSC click and a GA4 session are different populations counted different ways and shouldn't be expected to match. That caveat exists because reconciling those two numbers is the single most common way a Search Console analysis goes wrong.

And then stop re-running it

Any query worth running twice can be pinned to a live URL that refreshes itself as data syncs:

terminal
tablebi pin --title "Search performance" \
  --widget "Daily clicks (28d)::line=SELECT date, SUM(clicks) AS clicks FROM search_console_raw …" \
  --widget "Top queries=SELECT query, SUM(impressions) AS imp FROM search_console_raw …"
✓ published → https://dk.tablebi.com/d/dsh_…  (public, read-only, self-refreshing)

Here's a real one — live Search Console data across a portfolio of sites, pinned exactly this way:

When you should still write the client

Use the API directly if you're building a product feature on GSC data, if you need a dimension or a sync behavior no connector exposes, or if your compliance posture means the data can't transit a third party. Those are real reasons, and "just use a tool" would be bad advice for them.

Everyone else is usually solving a reporting problem, not an integration problem — and paying an integration tax for it. If that's you, the alternative isn't a different API, it's not writing one. For the analyst workflow on top of this data, see Claude Code for SEO; for the dashboard side, SEO dashboard in one command; and for the general pattern of giving a model a standing connection instead of exports, how to use Claude for data analysis.

FAQ

Is there an alternative to the Google Search Console API?

Several, depending on what you're optimizing for. Looker Studio's connector is free and code-free but keeps the data locked inside its reports. UI exports are instant but capped and static. A managed backend like TableBI connects GSC once via OAuth, syncs it into a table you query in read-only SQL, and lets you join it against GA4 and ad data. The API itself remains right if you're shipping a product on top of GSC data.

Can I query Search Console data with SQL?

Not directly — the API returns JSON, not a SQL surface, so anything cross-day means storing rows yourself first. TableBI does that step for you: synced data lands in a search_console_raw table with date, site, query, page, clicks, impressions and position, queried with ordinary read-only SQL.

How do I avoid writing OAuth and pagination code?

Use a connector that owns that layer. One tablebi connect gsc --site sc-domain:example.com opens a browser for authorization, then handles token refresh, day-by-day pagination, incremental syncing and retries. You never write a client, and never store a refresh token in your own repo.

Why is my Search Console data a few days behind?

That's Google, not your pipeline — GSC finalizes performance data roughly two to three days late, so the last couple of days always look artificially low. Anchor date filters to MAX(date) instead of today, and check the freshness block before you report a drop.

Try it

Get to the SQL query without writing the client.

terminal
npm i -g @tablebi/cli && tablebi connect gsc