google.com/goto: ler Location com HEAD
O Google Search já não coloca sempre a URL final no href do resultado. Os resultados orgânicos apontam para https://www.google.com/goto?url=CAES…. Não é o antigo google.com/url?q=…: o parâmetro não é uma URL codificada. Não se decodifica.
O Google tem de conhecer o destino na mesma. Coloca-o no cabeçalho HTTP Location quando se pede /goto. É essa a leitura que usamos.
Exemplos em curl, Python e Node: github.com/automdev/google-goto-url-fix. A API Google Search da Autom faz o hop no servidor.
O rollout e o porquê: google.com/goto: o anti-scraping do Google.
Uma frase
Não siga o redirecionamento. Leia 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 pede só cabeçalhos. GET com redirect: "manual" (ou allow_redirects=False) faz a mesma leitura. Por vezes o Google responde 402 (ou outro estado) com Location: leia o cabeçalho mesmo que não seja um 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 é HEAD. Sem -L, o curl não segue. A linha Location: é a URL real.
A mesma leitura com 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"))
Se HEAD vier vazio, tente de novo com GET sem 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"));
Num browser, um 3xx em redirect: "manual" pode chegar como opaqueredirect e esconder o cabeçalho. Em Node, os cabeçalhos são visíveis.
Porque não decodificar CAES?
O blob não é um protobuf de URL pública. É uma referência opaca. Só o Google conhece o destino e coloca-o em Location no hop. Inventar uma URL a partir de um nome visível ("LinkedIn · Satya Nadella") é má ideia.
O href é /goto. A página ainda conhece a URL.
O Google não consegue esconder o destino por completo. Precisa da URL real para desenhar a SERP: o domínio visível, o favicon, o bloco de atribuição. Esses valores continuam na página, em geral num script de dados no fim, e num store interno (W_jd) que o JavaScript da SERP lê.
Por isso, nalguns browsers, os links «limpam-se» depois de mover o rato: um script lê W_jd e reescreve cada href /goto com a URL real. Só cobre orgânico sob #rso div[data-rpos] com bloco de atribuição. Os AI Overviews ficam em /goto. É preciso uma página live e esse primeiro movimento do rato. Um fetch headless do HTML não dispara isto. O Chrome costuma deixar os href /goto como estão.
Outra fuga está no link «Traduzir esta página». Se o idioma da UI não coincide com o dos resultados, o Google acrescenta esse controlo e a URL limpa costuma ir lá. O latim (Accept-Language: la) aparece quase sempre, porque quase nenhuma página está em latim.
São explicações do que a página ainda contém. São frágeis: o Google pode mudar o nome de W_jd, alterar o script ou retirar o controlo de tradução. Também não dão um campo API estável.
A leitura que se aguenta é Location em /goto. Sem DOM live, sem evento de rato, sem truque de idioma.
Na Autom
A API Google Search já resolve /goto e devolve a URL final em 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 e README: github.com/automdev/google-goto-url-fix.
Leituras relacionadas
- google.com/goto: o anti-scraping do Google
- Google eliminou num=100
- Google processa SerpAPI: o que SearchGuard revela
1.000 pedidos grátis nos preços Autom, chave API em app.autom.dev/register.