Você configura uma saída na Alemanha, o endereço geolocaliza corretamente, e o alvo mesmo assim trata a sessão como suspeita ou entrega conteúdo destinado a outro lugar. O IP estava certo. Todo o resto na requisição ainda descrevia um visitante em outro país.
Localização não é um único sinal. É um conjunto deles, e um visitante real os produz todos a partir do mesmo lugar, porque vêm de uma máquina em um país. Um scraper os monta a partir de fontes diferentes: o país vem de um parâmetro do proxy, o fuso horário do relógio do servidor, o locale de um padrão de biblioteca, e o cabeçalho de idioma de algo fixado no código. Quando essas informações discordam entre si, a contradição é mais detectável do que qualquer valor isolado, e ela também pode mudar o que você coleta.
Os sinais que precisam concordar
Seis coisas dizem a um site onde você está, e vale listá-las explicitamente porque a maioria dos scrapers controla apenas um ou dois.
O endereço IP é o sinal principal e aquele que o seu proxy define. Accept-Language é o cabeçalho HTTP que expressa preferência de idioma, e muitos sites servem conteúdo diretamente a partir dele. Fuso horário é observável em um navegador por meio da API de data do JavaScript e, com mais precisão, pelo fuso horário resolvido pela API Intl. Locale abrange navigator.language e as convenções de formatação que a API Intl resolve, que determinam como datas, números e moeda são exibidos. Moeda e unidades, quando um site permite que o cliente sinalize preferências. E resolução DNS, que parece não ter relação, mas tem: se o seu cliente resolve nomes de host localmente enquanto sai remotamente, a resolução acontece a partir da sua localização e pode entregar um endpoint regionalmente incorreto, o que é o problema de vazamento de DNS.
Para trabalho HTTP simples, apenas os dois primeiros e o DNS são visíveis, motivo pelo qual o artigo sobre cabeçalhos trata o Accept-Language como o pareamento principal. Para automação de navegador, os seis são observáveis, e é aí que as inconsistências costumam aparecer.
Derive tudo de uma única fonte de verdade
A correção é estrutural, não uma lista de verificação. Se o país é escolhido em um lugar e o fuso horário em outro, eles vão divergir na primeira vez que alguém adicionar um mercado. Defina cada mercado uma única vez, com todos os sinais que ele implica, e derive a sessão inteira a partir desse registro.
MARKETS = {
"de": {"lang": "de-DE,de;q=0.9,en;q=0.8", "locale": "de-DE",
"tz": "Europe/Berlin", "currency": "EUR"},
"us": {"lang": "en-US,en;q=0.9", "locale": "en-US",
"tz": "America/New_York", "currency": "USD"},
"jp": {"lang": "ja-JP,ja;q=0.9,en;q=0.8", "locale": "ja-JP",
"tz": "Asia/Tokyo", "currency": "JPY"},
"br": {"lang": "pt-BR,pt;q=0.9,en;q=0.8", "locale": "pt-BR",
"tz": "America/Sao_Paulo", "currency": "BRL"},
}
def proxy_for(country, session=None):
user = f"customer-USERNAME-country-{country}"
if session:
user += f"-sid-{session}-ttl-600"
url = f"http://{user}:PASSWORD@p.shifter.io:443"
return {"http": url, "https": url}
Agora um mercado é um único argumento, e não há nenhum caminho de código em que o país e o fuso horário possam discordar, porque ninguém os define separadamente.
Aplicando isso a uma sessão de navegador
Frameworks de automação de navegador expõem fuso horário e locale como opções de contexto, que é o lugar correto para defini-los: eles se aplicam antes que qualquer script da página seja executado, então a página não consegue observar os valores reais da máquina.
# Playwright: proxy, fuso horário e locale, todos derivados de um único registro de mercado
m = MARKETS[country]
context = browser.new_context(
proxy={"server": "http://p.shifter.io:443",
"username": f"customer-USERNAME-country-{country}-sid-{sid}",
"password": "PASSWORD"},
locale=m["locale"], # navigator.language e formatação da Intl
timezone_id=m["tz"], # fuso horário resolvido pela Intl e offset do Date
extra_http_headers={"Accept-Language": m["lang"]},
)
Definir isso no nível do contexto, em vez de corrigir propriedades depois, é importante, porque um Intl.DateTimeFormat corrigido que discorda do offset do Date é em si uma inconsistência detectável, e scripts de detecção rotineiramente cruzam os dois valores.
Precisão, e quanto dela você precisa
Granularidade de país é suficiente para a maioria dos trabalhos, já que fuso horário e locale são, em grande parte, nacionais. Três casos exigem mais cuidado.
Países com múltiplos fusos horários tornam um padrão nacional incorreto para parte da população. Uma saída nos EUA é plausível em qualquer um de vários fusos, então, se você estiver trabalhando com segmentação em nível de cidade, deve derivar o fuso horário da cidade, e não do país; se não estiver, escolha o fuso que corresponde à maior parcela dos usuários e mantenha-o consistente, em vez de aleatorizar.
Países com múltiplos idiomas oficiais exigem uma escolha deliberada: uma saída suíça ou canadense pode plausivelmente ser vários locales, e a resposta correta costuma ser aquela que corresponde ao conteúdo que você está coletando, mantida constante.
Diferenças regionais de formatação são mais sutis e raramente valem a pena perseguir, mas se você apresentar um locale, deixe a API Intl fazer a formatação em vez de criar manualmente formatos de data e número que podem não corresponder ao que aquele locale realmente produz.
Consistência ao longo da vida de uma sessão
Uma sessão é uma história, e a história não pode mudar no meio do caminho. Se uma sessão fixa mantém um endereço para um fluxo de múltiplas etapas, cada requisição desse fluxo deve carregar o mesmo idioma, fuso horário e locale. Mudar qualquer um deles no meio do fluxo descreve um visitante que mudou de país entre clicar em pesquisar e ver um resultado, o que é uma anomalia mais forte do que qualquer incompatibilidade estática.
É aqui que derivar de um único registro de mercado compensa novamente: o identificador de sessão e o pacote de locale vêm do mesmo lugar e duram pelo mesmo período. Vincule-os explicitamente, de modo que liberar a sessão libere toda a identidade, e uma nova sessão comece uma identidade nova e internamente consistente. A mesma lógica rege o pareamento de fingerprints de dispositivo com identidade de rede em navegadores antidetecção.
Verificando se você acertou
Não presuma nada e verifique os dois níveis.
Primeiro, o que o navegador informa sobre si mesmo. Execute uma página que leia o fuso horário resolvido, navigator.language, e uma data formatada, e confirme que correspondem ao mercado pretendido. Isso detecta erros de configuração imediatamente.
JSON.stringify({
tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
lang: navigator.language,
langs: navigator.languages,
offset: new Date().getTimezoneOffset(),
})
Segundo, e mais significativo, o que o alvo faz. Busque uma página sensível à geolocalização e confirme que a moeda, o idioma e o conteúdo regional são o que um visitante local veria. O próprio comportamento do site é o veredito real, já que bancos de dados de geolocalização e a opinião de um alvo nem sempre concordam, e é para isso que serve o teste de precisão de localização. Se o endereço geolocaliza corretamente mas o conteúdo está errado, suspeite da resolução DNS antes de qualquer outra coisa.
Conclusão
Localização é um conjunto de sinais, e um site os lê em conjunto. Definir um país no proxy enquanto deixa fuso horário, locale e idioma no que quer que seja o padrão do seu servidor produz um visitante que não pode existir, o que é ao mesmo tempo um sinal de detecção e uma fonte de dados silenciosamente errados. Defina cada mercado uma única vez com todos os sinais que ele implica, derive os parâmetros do proxy e o contexto do navegador a partir desse único registro para que não possam divergir, defina fuso horário e locale no nível de contexto em vez de corrigi-los após o carregamento, mantenha o pacote inteiro constante durante toda a vida de uma sessão, e verifique nos dois níveis, o que o navegador informa e o que o alvo realmente entrega. Aí, a única coisa que o seu tráfego diz sobre sua localização é a única coisa que você escolheu.
A geografia em si vem dos proxies residenciais, endereços reais de nível doméstico com segmentação por país e cidade, então a localização que a sua sessão afirma é uma localização da qual você realmente está saindo, com preços por GB adequados para rodar o mesmo trabalho em vários mercados.