google.com/goto: leer Location con HEAD
Google Search ya no siempre pone la URL final en el href del resultado. Los resultados orgánicos apuntan a https://www.google.com/goto?url=CAES…. No es el antiguo google.com/url?q=…: el parámetro no es una URL codificada. No se decodifica.
Google tiene que conocer el destino de todos modos. Lo pone en el encabezado HTTP Location cuando pides /goto. Esa es la lectura que usamos.
Ejemplos en curl, Python y Node: github.com/automdev/google-goto-url-fix. La API Google Search de Autom hace ese hop en el servidor.
El despliegue y el porqué: google.com/goto: el anti-scraping de Google.
Una frase
No sigas la redirección. Lee Location.
GET /goto?url=CAES… HTTP/1.1
Host: www.google.com
HTTP/1.1 302 Found
Location: https://www.linkedin.com/in/satyanadella
HEAD pide solo cabeceras. GET con redirect: "manual" (o allow_redirects=False) hace la misma lectura. A veces Google responde 402 (u otro estado) con Location: lee el encabezado aunque no sea un 3xx.
curl
curl -sI --max-redirs 0 \
-H 'Referer: https://www.google.com/search' \
'https://www.google.com/goto?url=CAES...' \
| grep -i '^location:'
-I es HEAD. Sin -L, curl no sigue. La línea Location: es la URL real.
La misma lectura con GET:
curl -sD - -o /dev/null --max-redirs 0 \
-H 'Referer: https://www.google.com/search' \
'https://www.google.com/goto?url=CAES...' \
| grep -i '^location:'
Python
import requests
goto = "https://www.google.com/goto?url=CAES..."
r = requests.head(
goto,
allow_redirects=False,
headers={"Referer": "https://www.google.com/search"},
timeout=10,
)
print(r.status_code, r.headers.get("Location"))
Si HEAD viene vacío, reintenta con GET sin seguir:
r = requests.get(goto, allow_redirects=False, timeout=10)
print(r.headers.get("Location"))
Node
const res = await fetch(goto, {
method: "HEAD",
redirect: "manual",
headers: { Referer: "https://www.google.com/search" },
});
console.log(res.status, res.headers.get("location"));
En un navegador, un 3xx en redirect: "manual" puede llegar como opaqueredirect y ocultar el encabezado. En Node, las cabeceras son visibles.
¿Por qué no decodificar CAES?
El blob no es un protobuf de URL pública. Es una referencia opaca. Solo Google conoce el destino y lo pone en Location en el hop. Reconstruir una URL a partir de un nombre visible ("LinkedIn · Satya Nadella") es mala idea.
El href es /goto. La página sigue sabiendo la URL.
Google no puede ocultar el destino por completo. Necesita la URL real para pintar la SERP: el dominio visible, el favicon, el bloque de atribución. Esos valores siguen en la página, suele ser en un script de datos al final, y en un almacén interno (W_jd) que lee el JavaScript de la SERP.
Por eso, en algunos navegadores, los enlaces «se limpian» tras mover el ratón: un script lee W_jd y reescribe cada href /goto con la URL real. Solo cubre orgánicos bajo #rso div[data-rpos] con bloque de atribución. Los AI Overviews se quedan en /goto. Hace falta una página live y ese primer movimiento de ratón. Un fetch headless del HTML no lo dispara. Chrome suele dejar los href /goto como están.
Otra fuga está en el enlace «Traducir esta página». Si el idioma de la UI no coincide con el de los resultados, Google añade ese control y la URL limpia suele ir ahí. El latín (Accept-Language: la) aparece casi siempre, porque casi ninguna página está en latín.
Son explicaciones de lo que la página todavía contiene. Son frágiles: Google puede renombrar W_jd, cambiar el script o quitar el control de traducción. Tampoco te dan un campo API estable.
La lectura que aguanta es Location en /goto. Sin DOM live, sin evento de ratón, sin truco de idioma.
En Autom
La API Google Search ya resuelve /goto y devuelve la URL final en organic_results[].link.
curl -s https://api.autom.dev/v1/google/search \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"linkedin.com/in satya nadella","gl":"us","hl":"en"}'
Código y README: github.com/automdev/google-goto-url-fix.
Lecturas relacionadas
- google.com/goto: el anti-scraping de Google
- Google eliminó num=100
- Google demanda a SerpAPI: lo que revela SearchGuard
1.000 solicitudes gratis en precios Autom, clave API en app.autom.dev/register.