magstags

Google /goto redirects: how to get the real URL

Right-click a Google result and choose Copy link address. On affected results, you no longer get the page URL. You get this:

https://www.google.com/goto?url=CAESVAHrOzAVnxj44DGxhaQDKUnk…

Hovering is no better. Chrome's status bar shows the same Google URL.

Google confirmed the rollout on 26 August 2026, after the behaviour had already been appearing in testing. For normal searching, there is not much to notice: click the result and you still arrive at the page.

For SEO work, it is more annoying. The destination URL is no longer sitting in the result's href, which means you cannot inspect it on hover, copy it into a sheet, or pull it directly out of the HTML.

Testing note: I tested this in Chrome on google.com (Poland, English interface) on 11–12 September 2026, while building the extension I use to resolve the links. Google is not serving the same link format to every browser, result type or session. Where the behaviour below comes from someone else's testing rather than mine, I've said so.

What changed in the link

A normal Google result used to be fairly useful HTML:

<a href="https://www.nike.com/gb/"
   ping="/url?sa=t&url=https://www.nike.com/gb/&ved=…">
  <h3>Nike. Just Do It. Nike GB</h3>
</a>

The destination stayed in href. Google could handle click tracking separately through ping.

On affected results, the link now looks like this:

<a href="https://www.google.com/goto?url=CAESVAHrOzAVnxj44DGxhaQDKUnk…">
  <h3>Nike. Just Do It. Nike GB</h3>
</a>

The CAES… value is not the destination URL with some inconvenient encoding on top.

You can Base64URL-decode it. You can parse the protobuf envelope. On the token above, field 1 is the integer 1 and field 2 contains 84 bytes of binary data.

What you do not get is a URL.

ScrapingBee tested 324 tokens and found the same basic envelope each time, including a consistent prefix on the binary payload and data behaving like cryptographic output. My tokens have the same structure. I have not found a published method that gets from that payload back to the destination locally, and I would not build anything around the assumption that one is coming.

The useful part happens when you send the token back to Google:

GET /goto?url=CAES…

302 Found
Location: https://www.nike.com/gb/

The Location header is the destination.

No decoding trick required. You ask Google where the token goes.

The redirect also does not appear to be tied to the browser session that produced it. A token I collected on 11 September still resolved on the 12th. ScrapingBee resolved tokens days later and from different connections without carrying over the original cookies or browser session.

That does not make /goto links good identifiers. Their maximum lifetime is unknown, and the same destination can receive a different token on another SERP. Resolve them when you need them; store the destination, not Google's token.

What this breaks

Hover no longer tells you where the result goes

Chrome's status bar shows google.com/goto?url=… rather than the destination.

That removes a small but useful check when you are looking at country variants, tracking domains, unexpected hosts, or simply trying to make sure the result goes where you think it does.

Copy link address copies the redirect

Chrome is doing exactly what it is supposed to do. The href contains a Google URL, so that is what Copy link address copies.

Paste it into a spreadsheet and you have a long opaque token where you expected the page URL.

Parsing the HTML gets you the same problem

Anything that previously extracted organic destinations from href now gets /goto tokens instead.

Resolving those tokens adds another Google request for every unique wrapped URL you actually need.

This comes on top of Google's removal of num=100 in 2025. Fetching roughly 100 results already went from one SERP request to around ten. /goto adds a second problem after you have the results: finding out where the wrapped ones lead.

Use GET, not HEAD. This one cost me more time than it should have. A HEAD request to /goto returned 200 without a Location header in my testing. A normal GET returned the expected 302. ScrapingBee found the same thing. So if you have written a resolver, it gets a response, and somehow Google never appears to redirect anywhere, check the request method before checking everything else.

How to get the real URL

For one result: click it

The obvious option. Fine if you only need one URL and do not care about checking it first. You visit the destination, read the address bar, done.

For one result without visiting the destination: read the 302

Copy the /goto URL and request it without following redirects:

curl -sS -D - -o /dev/null \
  "https://www.google.com/goto?url=CAES…" \
  | grep -i '^location:'

Do not add -L. You want curl to stop at Google's response rather than follow the redirect. The result is:

location: https://www.nike.com/gb/

Google gets the /goto request. The destination site does not.

Good for one URL. Tedious for twenty.

If you are working in the SERP: resolve it there

Copying tokens into a terminal gets old fairly quickly, so I built Google Goto URL Resolver for Chrome.

Hover a result and it resolves the destination. If you want the old behaviour back more fully, it can rewrite the result so Chrome's status bar and Copy link address use the destination again.

It can also resolve the current page and export the results as URLs, Markdown or CSV, which is the part I actually wanted when auditing SERPs.

Resolution still goes through Google's /goto endpoint. The extension does it one link at a time and caches the answer for the browser session.

Not every Google link uses /goto

This is where it gets slightly untidy.

In my Chrome tests, image-pack tiles, sitelinks beneath the main result and the “Read more” links with #:~:text= fragments still had their destination directly in href, with tracking handled separately through ping.

Organic title links and results inside grouped related-results sections were the ones getting /goto.

Do not assume that is the universal layout. ScrapingBee saw /goto in Chrome and Edge, direct links in Brave and LibreWolf, and a different /url?...&url=CAES… wrapper in Safari.

So if you are parsing Google results yourself, inspect what you are actually being served before writing the selector and calling the job finished.

Things I found while building the resolver

This is the bit I wish had existed before I started.

Rewriting href once isn't enough

My first version found the /goto links, resolved them, replaced href and looked finished.

Then I clicked one.

Google's own page script had put the redirect back.

The results page uses an interaction handler, google.arwt, which can reassign the link on mousedown. Rewriting the DOM once on page load therefore works right up until someone interacts with the result.

I tried reapplying the destination on mousedown in the capture phase. Google's handler still ran afterwards and changed it back.

What worked was reasserting the resolved URL on click and auxclick, after Google's handler has done its work and immediately before navigation.

If you are writing your own fix, inspect the URL when the link is actually clicked. The DOM looking correct while you stare at DevTools does not prove very much.

Resolve duplicate tokens once

The same destination can turn up several times on one results page: as the main organic result, in a related-results block, as an image source, or elsewhere in the page. Search for a brand and nike.com/gb/ can appear in all three.

ScrapingBee found identical /goto tokens repeated within the same SERP.

If you are resolving programmatically, dedupe identical tokens before sending requests.

If you are building a list of results, dedupe the final data on the resolved destination URL. The same page will not necessarily have the same token on another results page.

Those are two different dedupe jobs.

“Translate this page” needs its own handling

In the results I tested, Google's translation links were wrapped too. Resolving them led to a translate.google.com/translate?u=… URL rather than directly to the page.

They also carry hreftranslate, which is a much cleaner way to identify them than matching “Translate this page” text and then discovering Google has changed the interface language.

If you are exporting organic destinations, you probably want to exclude them.

fetch() does not give you the redirect header

My first instinct for the extension was the obvious one:

fetch(url, { redirect: "manual" })

That does not give an extension the Location header.

For a manual cross-origin redirect, Fetch exposes an opaqueredirect response: status 0, no readable headers and no useful body.

So the extension observes the redirect through Chrome's webRequest API instead.

That is why it needs the permission. It is not inspecting the destination site; it needs to see the response Google sends before Chrome follows it.

The referrer does not change

The extra redirect looks as though it ought to add another attribution problem, but in practice it does not.

Google Search already uses an origin referrer policy. Destination sites therefore saw https://www.google.com/ rather than the full results-page URL before /goto, and they still do now.

So this changes how you inspect and collect result URLs. It does not change ordinary Google organic attribution in your analytics.

Frequently asked questions

Is /goto the same as Google's old /url?q= redirect?

No. The older format carried the destination in a readable parameter: /url?q=https://www.nike.com/gb/&sa=…. You could extract the URL directly from the link. With /goto?url=CAES… the parameter is an opaque token. There is no destination URL sitting in the query string waiting to be decoded.

Can the CAES token be decoded?

Partly. The Base64URL layer decodes. The protobuf structure parses. What remains is protected binary rather than a readable destination. I can get into the container; I cannot turn its payload into the URL. For practical purposes, resolution still means sending the token to Google's /goto endpoint with a GET and reading the 302 Location header.

Why does Copy link address give me a Google URL?

Because that is now the link. Chrome copies the value of href, and on affected results href points to google.com/goto. Resolve it first if you need the destination instead.

Does Google Goto URL Resolver resolve the whole web?

No. It runs only on Google Search results pages and deals with the links on the current page. Hover mode resolves a result when you point at it. Automatic mode works through the result links one at a time and caches them for the session. It is a browser tool for working with SERPs, not a bulk Google scraper.

Sources and further reading

Written by
Portrait of Mags Sikora
Senior SEO Consultant, SEO Director

Senior SEO Consultant with 18+ years leading search programmes for enterprise and global businesses. Specialises in the parts of SEO that are hard to fake and harder to fix: technical architecture, structured data, and international implementations.

On this page