Skip to content

New Official SDKs for TypeScript, Python and Go

SerpKite
Get API key

Google /goto links broke your rank tracker: here's the fix

In August 2026 Google started serving encoded /goto redirect URLs in place of destination links. Parsers that read href directly now see google.com. How to detect it and fix it.

SerpKite team 2 min read

On this page

On August 26, 2026, it was confirmed that Google now serves result links as encoded /goto redirect URLs instead of the destination URL. If your parser reads the href of a result, it now gets a Google URL, not the page that ranks.

For rank trackers this is quietly destructive. Nothing errors. You just stop finding your domain.

The symptoms

  • Tracked domains “drop out” of the top 100 overnight, across many keywords at once.
  • Result links in your database all start with a Google host.
  • Domain-level aggregates (share of voice, competitor visibility) collapse into one domain: Google’s.
  • Deduplication by URL goes wrong because every link looks similar.

If you use a SERP API rather than your own parser, the same symptoms mean your vendor didn’t handle it.

Why it happens

Google has always wrapped some links for click tracking. The difference with /goto is that the destination is encoded rather than sitting in a readable query parameter, so the old trick of pulling ?url= out of the link no longer works everywhere. This is one of a series of changes, alongside the JavaScript requirement in January 2025 and the removal of num=100 in September 2025, that make naive scraping fail silently rather than loudly.

The fix

There are two ways to get the real URL back:

  1. Decode the redirect when the destination can be recovered from the link itself.
  2. Follow the redirect (without executing the page) and record where it lands.

Either way, normalize the result: lowercase the host, strip www., and store a canonical domain alongside the full link, so domain matching doesn’t depend on URL formatting.

Then add a guardrail so this can’t happen silently again:

from urllib.parse import urlparse

def assert_resolved(results):
    bad = [r["link"] for r in results if urlparse(r["link"]).hostname.endswith("google.com")]
    if bad:
        raise ValueError(f"{len(bad)} unresolved Google redirect links, e.g. {bad[0]}")

Run it on a sample of every crawl. If it fires, stop writing positions until the parser is fixed; bad data is worse than a gap.

How SerpKite handles it

Every organic result’s link is the resolved destination URL, never a Google redirect, and every result carries a canonical domain. The response also reports meta.resolved_urls: true, so you can assert on it:

data = res.json()
assert data["meta"]["resolved_urls"], data["meta"]["request_id"]
positions = {r["domain"]: r["position"] for r in data["results"]}

For top-100 tracking

Use num=100 to get the top 100 in one call (7 credits), or queue checks with POST /v1/batches to pay half. See num=100 is gone for the cost math.

We log changes like this one on the Google SERP changelog. If you’re building a tracker, the Rank Tracker API page has a worked example.

Related posts

3 min read

Introducing SerpKite

A Google search API built for AI agents: clean JSON or Markdown, official TypeScript/Python/Go SDKs, native LangChain, CrewAI and MCP, and credits that never expire.

Start building

Get your API key in 30 seconds

2,500 free credits, then 1,000 every month. No credit card.