Resposta curta
ERR_TOO_MANY_REDIRECTS é o navegador desistindo de um loop de redirecionamento: a URL A manda pra B, B manda de volta pra A, e isso nunca termina. Na maioria das vezes, duas camadas brigam pela mesma decisão, uma forçando https e outra devolvendo pra http, ou uma mandando pra www e outra tirando o www. O caso mais comum é a Cloudflare no modo Flexível na frente de um servidor que força https: troque o modo pra Full (strict). Pra achar a camada culpada, rode curl -sSIL --max-redirs 20 e leia os Location. Limpar cookies só resolve quando o loop depende de cookie.
O que é ERR_TOO_MANY_REDIRECTS (e o texto exato de cada navegador)
Todo redirect é uma resposta 3xx com um cabeçalho Location dizendo pra onde ir. Quando a sequência volta a um endereço que já passou, ou fica longa demais, o navegador para e mostra a página de erro. O site não está fora do ar: o servidor responde, só que nunca com a página.
No Chrome em português, a tela de erro mostra:
- o título Esta página não está funcionando;
- a frase Redirecionamento em excesso por seusite.com.br (em inglês, seusite.com.br redirected you too many times, que muita gente procura traduzido como "redirecionou você muitas vezes");
- a sugestão Tente excluir os cookies;
- o código
ERR_TOO_MANY_REDIRECTSembaixo.
No Firefox, a página diz que o Firefox detectou que o servidor está redirecionando a requisição para este endereço de uma forma que nunca será concluída, e completa: "Às vezes, esse problema pode ser causado pela desativação ou recusa em aceitar cookies".
Os navegadores sugerem cookies porque é o que dá pra mexer do lado de quem visita. Mas um loop que vem do servidor ou da CDN acontece pra todo mundo, com ou sem cookie.
Primeiro teste: é o site ou é o seu navegador?
- Abra o endereço numa janela anônima. Ela começa sem cookies. Se lá funciona e na janela normal não, o problema é cookie (pule pra quando é cookie).
- Teste de outra rede, como o 4G do celular. Se funciona fora e falha na sua rede, desconfie de proxy da empresa ou de DNS antigo em cache.
- Rode o curl (próxima seção). O curl não guarda cookie entre execuções, então, se ele também entra em loop, o problema está no site, e é ele que você vai corrigir.
Teste sempre as quatro portas de entrada: http://seusite.com.br, http://www.seusite.com.br, https://seusite.com.br e https://www.seusite.com.br. Às vezes só uma delas entra em loop, e é justamente a que o Google ou um link antigo usa.
Como ver a cadeia de redirecionamento com curl
O comando abaixo faz requisições HEAD (-I), segue os redirects (-L) e para depois de 20 saltos. O -sS esconde a barra de progresso mas mantém a mensagem de erro, que é justamente o aviso de loop. O grep deixa só o código de cada resposta e o destino:
curl -sSIL --max-redirs 20 https://seusite.com.br | grep -iE '^(HTTP|location|server)'Um loop clássico de Cloudflare no modo Flexível aparece assim:
HTTP/2 301
location: https://seusite.com.br/
server: cloudflare
HTTP/2 301
location: https://seusite.com.br/
server: cloudflare
HTTP/2 301
location: https://seusite.com.br/
server: cloudflare
...
curl: (47) Maximum (20) redirects followedComo ler:
- O
locationé igual ao endereço pedido. A URL redireciona pra ela mesma. Quem responde acha que a conexão chegou em http, mesmo ela tendo chegado em https. É o sintoma de proxy na frente (Cloudflare Flexível, balanceador) e servidor que força https sem saber disso. - Dois endereços se alternando.
seusite.com.brmanda prawww.seusite.com.br, que manda de volta. São duas camadas com opiniões opostas sobre o www. - http e https se alternando. Uma camada força https, outra força http. Na Cloudflare, é Always Use HTTPS ou HSTS contra um servidor que redireciona pra http.
- Barra no fim indo e voltando.
/blogvai pra/blog/, que volta pra/blog. Uma regra põe a barra e outra tira. - O endereço cresce a cada salto.
/pt/pt/pt/...ou?redirect=...dentro de outro?redirect=. A regra casa com o próprio destino e aplica de novo.
A linha server ajuda a saber quem respondeu. cloudflare não quer dizer que a Cloudflare criou o redirect: ela também entrega os redirects que o seu servidor manda. Pra separar, pergunte direto ao servidor de origem, pulando a CDN (troque o IP pelo do seu servidor):
curl -sI --resolve seusite.com.br:80:203.0.113.10 http://seusite.com.br | grep -iE '^(HTTP|location)'Se a origem responde 301 pra https quando recebe http, e a CDN fala http com ela, você achou o loop.
Se o servidor responde diferente a HEAD, troque -I por um GET que mostra os cabeçalhos de cada salto:
curl -sSL --max-redirs 20 -o /dev/null -D - https://seusite.com.br | grep -iE '^(HTTP|location)'Sem terminal, o verificador de redirect faz a mesma coisa no navegador: segue cada salto, mostra o código e o destino de cada um e avisa quando a corrente passa do limite de saltos.
No Chrome: DevTools com Manter registro
- Abra o DevTools (F12, ou Ctrl+Shift+I; no Mac, Cmd+Option+I) e vá pro painel Network (Rede).
- Marque Manter registro (Preserve log), senão a lista é apagada a cada redirect, e marque Desativar cache (Disable cache) pra não ver um 301 guardado de antes.
- Recarregue a página. Cada linha com status 301, 302, 307 ou 308 é um salto.
- Clique numa linha, abra a guia Cabeçalhos (Headers) e veja o
locationem Cabeçalhos de resposta. Se aparecerset-cookieem cada salto, guarde essa pista.
Atenção ao cache: redirect 301 e 308 ficam guardados no navegador. Depois de corrigir, teste com o curl ou numa janela anônima, senão você continua vendo o loop antigo.
Onde aparece, causa provável, onde corrigir
| O que a cadeia mostra | Causa provável | Onde corrigir |
|---|---|---|
https pro mesmo https, com server: cloudflare | Cloudflare em Flexível e servidor forçando https | Cloudflare, SSL/TLS, Visão geral: modo Full (strict) |
| https vai pra http, http volta pra https | Always Use HTTPS ou HSTS na Cloudflare e servidor mandando pra http | Remover o redirect pra http no servidor |
| Site na Vercel atrás da Cloudflare, loop em tudo | Flexível: a Vercel sempre manda http pra https com 308 | Cloudflare: Full (strict), ou DNS only |
| sem www vai pra www, www volta pra sem www | Domínio da plataforma e regra da CDN em sentidos opostos | Escolher uma camada só pra decidir o www |
WordPress: loop no site todo ou só no /wp-admin | siteurl/home errados ou WordPress atrás de proxy sem saber que é https | wp-config.php ou tabela wp_options |
/pagina e /pagina/ se alternando | trailingSlash do Next.js contra regra de barra da hospedagem ou do servidor | Deixar uma regra de barra só |
| URL cresce ou repete pedaço a cada salto | Regra de .htaccess, nginx ou next.config que casa com o próprio destino | A regra, com condição que exclui o destino |
| Funciona na janela anônima, falha na normal | Cookie velho ou corrompido | Excluir os cookies do site (e corrigir a lógica de login) |
Cloudflare: modo Flexível, Always Use HTTPS e regras de redirecionamento
A página de solução de problemas de ERR_TOO_MANY_REDIRECTS da Cloudflare lista três origens: o modo de criptografia SSL/TLS, as opções da página Edge Certificates e regras de redirecionamento conflitantes. Em quase todas, o redirect do próprio servidor de origem participa do loop.
Os modos de criptografia e onde cada um quebra
| Modo | Visitante até a Cloudflare | Cloudflare até o seu servidor | Quando dá loop |
|---|---|---|---|
| Off | http | http | Com HSTS ligado |
| Flexible (Flexível) | Pode ser https | Sempre http | Servidor redireciona http pra https |
| Full | http ou https | Mesmo protocolo do visitante, sem validar o certificado | Servidor redireciona https pra http, com Always Use HTTPS ou HSTS ligado |
| Full (strict) | http ou https | Mesmo protocolo do visitante, validando o certificado | Servidor redireciona https pra http, com Always Use HTTPS ou HSTS ligado |
O loop do Flexível acontece assim: o visitante chega em https, a Cloudflare pede a página ao seu servidor em http, o servidor responde "vá pra https", a Cloudflare repassa, o navegador pede https de novo, e o ciclo recomeça. O servidor nunca vê um https, então nunca para de redirecionar.
Pra corrigir:
- No painel da Cloudflare, abra o domínio e vá em SSL/TLS, Overview (Visão geral).
- Troque o modo pra Full (strict). Ele exige um certificado válido no servidor: o de uma autoridade pública, como o Let's Encrypt, ou um Origin CA da própria Cloudflare. Vercel e Netlify já entregam certificado válido.
- Se o servidor ainda não tem certificado, a alternativa da Cloudflare é tirar o redirect pra https do servidor e forçar https na borda, com Always Use HTTPS.
A Cloudflare recomenda Full ou Full (strict) sempre que possível. Se o seu painel mostra a criptografia em modo automático, a Cloudflare escaneia a origem e sobe o modo sozinha quando é seguro, mas nunca rebaixa. Um modo Flexível antigo, escolhido à mão, continua lá até você trocar.
Always Use HTTPS e HSTS contra o servidor
Always Use HTTPS fica em SSL/TLS, Edge Certificates, e manda todo http pra https em todos os subdomínios. Dá loop se o servidor manda https de volta pra http (é comum num servidor antigo configurado só pra http). A correção é remover o redirect pra http no servidor ou desligar a opção. Com HSTS ligado, o próprio navegador converte http em https, então o mesmo redirect pra http no servidor vira loop, e o modo Off também.
A Cloudflare desaconselha fazer o redirect pra https no servidor quando ele já está atrás dela: o lugar certo é a borda, com Always Use HTTPS. Escolha uma camada pra essa decisão.
Regras de redirecionamento que brigam
Redirect Rules (em Rules, Overview, Create rule, Redirect Rule) e as Page Rules antigas também podem formar loop entre si ou com o servidor. O exemplo da própria Cloudflare: https://a.example.com manda pra http://b.example.com, que manda de volta pra https://a.example.com. Revise as regras dos dois hosts juntos. Uma regra correta de www pra sem www, no modo Wildcard pattern:
Request URL: https://www.seusite.com.br/*
Target URL: https://seusite.com.br/${1}
Status code: 301
Preserve query string: ligadoEla só casa com o host www, então não pega o próprio destino. Se a hospedagem manda sem www pra www, fique com uma das duas regras.
Vercel e Netlify: www contra domínio raiz e a Cloudflare no meio
Vercel
Na Vercel, todo pedido http é redirecionado pra https com 308, e isso não pode ser desligado. Por isso, Vercel atrás da Cloudflare em Flexível entra em loop em todas as páginas: a Cloudflare pede em http, a Vercel responde 308 pra https, de novo e de novo. Corrija com Full (strict) ou deixe o registro como DNS only (nuvem cinza). A Vercel, aliás, não recomenda colocar proxy reverso na frente dela.
O outro loop clássico é o do www. O redirect entre domínios fica em Project Settings, Domains, Edit no domínio de origem, campo Redirect to. A Vercel recomenda o www como domínio principal. Se lá está "seusite.com.br vai pra www" e na Cloudflare existe uma regra "www vai pra seusite.com.br", uma desfaz a outra. Decida qual é o endereço principal e configure o redirect num lugar só. Se usar a Cloudflare só como DNS, deixe a decisão pra Vercel.
Netlify
Na Netlify, quando você adiciona o domínio raiz ou o www, os dois entram em Production domains, e o que não é o principal é redirecionado automaticamente pro principal. Se o principal é www e você escreve no _redirects, ou numa regra da CDN, o sentido contrário, o resultado é loop. Pra trocar o sentido, troque o domínio principal no painel em vez de criar uma regra por cima. Com DNS externo, a Netlify recomenda o www como principal.
WordPress: siteurl, home e o proxy na frente
Endereços errados nas configurações
O WordPress redireciona pra o endereço que tem salvo. Em Configurações, Geral, ficam o Endereço do WordPress (URL) (opção siteurl) e o Endereço do site (URL) (opção home). Os dois devem ter https:// e nenhuma barra no fim. Se um diz www e o servidor ou a CDN tira o www, ou se um diz http e algo na frente força https, nasce o loop.
Com o painel inacessível (o próprio /wp-admin em loop), a documentação do WordPress mostra como fixar os valores no wp-config.php:
define( 'WP_HOME', 'https://seusite.com.br' );
define( 'WP_SITEURL', 'https://seusite.com.br' );Com isso, os campos em Configurações, Geral ficam travados. A outra saída é editar direto no banco: na tabela wp_options (o prefixo pode ser outro), as linhas com option_name igual a siteurl e home. Faça backup antes.
WordPress atrás da Cloudflare ou de um balanceador
Quando o https termina no proxy e o WordPress roda sem https atrás dele, o WordPress acha que toda visita chega em http. Com FORCE_SSL_ADMIN ligado ou com o endereço em https, a documentação de HTTPS do WordPress avisa que as requisições caem num loop infinito de redirecionamento. A correção é ler o cabeçalho X-Forwarded-Proto, que a Cloudflare envia com o protocolo que o visitante usou. No wp-config.php, antes da linha que manda parar de editar:
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] )
&& strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) !== false ) {
$_SERVER['HTTPS'] = 'on';
}Se você usa a Cloudflare, o plugin oficial dela pra WordPress com a opção Automatic HTTPS rewrites também ajuda a evitar loop e conteúdo misto. E o modo Flexível continua sendo a primeira coisa a trocar.
Next.js: trailingSlash e redirects no next.config
Por padrão, o Next.js manda URLs com barra no fim pra versão sem barra: /sobre/ vai pra /sobre. Com trailingSlash: true, faz o contrário. O loop aparece quando outra camada tem a opinião oposta: uma regra de nginx que acrescenta barra, um trailingSlash diferente no vercel.json, uma Redirect Rule na CDN. Escolha uma e apague o resto.
module.exports = {
// uma decisão só sobre a barra final, e nenhuma regra igual no servidor ou na CDN
trailingSlash: false,
}Dois erros comuns dentro do redirects():
- Esquecer a barra antes dos dois-pontos. A documentação do Next.js avisa: sem a
/antes do:, o parâmetro vira texto literal e você corre o risco de criar redirect infinito. - Um
sourceque casa com o destino. Um/:path*que manda tudo pra/manutencaotambém casa com/manutencao. Exclua o destino com lookahead, como no exemplo da doc. Exclua também/_next/, senão os arquivos de CSS e JS da própria página de manutenção são redirecionados:
module.exports = {
async redirects() {
return [
{
// casa com tudo, menos com o próprio destino (com ou sem barra) e os arquivos do Next
source: '/:path((?!manutencao/?$|_next/).*)',
destination: '/manutencao',
permanent: false,
},
{
// host antigo pro novo: o has limita ao host de origem
source: '/:path*',
has: [{ type: 'host', value: 'seusite-antigo.com.br' }],
destination: 'https://seusite.com.br/:path*',
permanent: true,
},
]
},
}Sem o has, um redirect de host com destino absoluto pro mesmo domínio que serve o projeto casa com ele mesmo. O redirect de host também pode ser feito no painel da hospedagem; o que não pode é fazer nos dois lugares com sentidos diferentes.
nginx e .htaccess: a regra que casa com o próprio destino
nginx
O padrão sem loop é separar os blocos server por host e protocolo. Cada bloco só redireciona quem não está no endereço final, então o final nunca redireciona:
# http, com e sem www: um salto pro endereço final
server {
listen 80;
server_name seusite.com.br www.seusite.com.br;
return 301 https://seusite.com.br$request_uri;
}
# https com www: vai pro sem www
server {
listen 443 ssl;
server_name www.seusite.com.br;
# ssl_certificate e ssl_certificate_key aqui
return 301 https://seusite.com.br$request_uri;
}
# https sem www: é o endereço final, nada de redirect aqui
server {
listen 443 ssl;
server_name seusite.com.br;
# ssl_certificate e ssl_certificate_key aqui
root /var/www/seusite;
}O loop aparece quando alguém coloca return 301 https://... dentro do bloco que já é o final, ou testa $scheme num servidor atrás de proxy. Atrás da Cloudflare em Flexível, toda requisição chega na porta 80, e o bloco de cima redireciona pra sempre. Se não dá pra mudar o modo, decida pelo cabeçalho que o proxy manda:
# atrás de proxy: só redireciona se o visitante usou http
server {
listen 80;
server_name seusite.com.br;
if ($http_x_forwarded_proto = "http") {
return 301 https://seusite.com.br$request_uri;
}
root /var/www/seusite;
}Apache (.htaccess)
Atrás de proxy, %{HTTPS} fica sempre off, e a regra clássica de forçar https vira loop. Olhe o X-Forwarded-Proto também:
RewriteEngine On
# 1. http vai pro endereço final, mas só se nem o servidor nem o proxy viram https
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://seusite.com.br%{REQUEST_URI} [L,R=301]
# 2. https com www vai pro sem www (o endereço final não casa com nenhuma das duas)
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^ https://seusite.com.br%{REQUEST_URI} [L,R=301]O outro erro comum é uma regra de caminho que casa com o destino, como RewriteRule ^(.*)$ /pt/$1 [R=301,L]: /pt/ também casa, vira /pt/pt/, e assim por diante. Ponha uma condição que exclui o destino (RewriteCond %{REQUEST_URI} !^/pt(/|$), que também deixa passar o /pt sem barra) antes da regra.
Quando é cookie (e quando limpar não adianta)
Limpar cookies resolve quando o redirect depende de um cookie: o login que manda pra /entrar quando a sessão é inválida e o /entrar que manda de volta porque acha que você está logado; um cookie de idioma ou região que não bate com a regra do servidor. O sinal é o que você viu no teste: funciona na janela anônima e falha na normal, e o curl chega à página.
Como quem visita: nas configurações do navegador, exclua os cookies só desse site, sem apagar tudo. Como dono do site: se usuários relatam o erro, a causa é a lógica que lê o cookie, e é ela que precisa de correção. Pedir pra cada visitante limpar cookies só esconde o problema.
Se o curl também entra em loop, cookie não é a causa. Volte pra cadeia e procure as duas camadas que brigam.
O que o Googlebot faz com um loop
Pela documentação sobre como os códigos de status HTTP afetam os rastreadores do Google, os rastreadores do Google seguem até 10 saltos de redirecionamento por padrão. Um loop nunca chega a uma página, então o Google não recebe conteúdo nenhum pra indexar.
No Search Console, em Indexação, Páginas, isso aparece no motivo Erro de redirecionamento, que o relatório de indexação de páginas define como um destes casos:
- uma cadeia de redirecionamento longa demais;
- um loop de redirecionamento;
- um URL de redirecionamento que excedeu o tamanho máximo;
- um URL inválido ou vazio na cadeia de redirecionamento.
Duas observações práticas. Primeira: a mesma documentação diz que as ferramentas de inspeção do Google não seguem redirecionamentos, então, na Inspeção de URL, inspecione o endereço final, não o de origem. Segunda: depois de corrigir, abra o motivo no relatório e clique em Validar a correção. O Search Console confere uma amostra, rastreia de novo as URLs afetadas, e o processo costuma levar até duas semanas.
Uma cadeia longa sem loop também custa: a diferença entre cadeia e loop, e quantos saltos manter numa migração, está no artigo sobre redirect 301 e 302. Se o loop pegou a home e o tráfego sumiu, veja também o que fazer quando o site sumiu do Google.
Como conferir que resolveu
- Rode o curl nas quatro entradas (http e https, com e sem www). Cada uma deve terminar em
200, no mesmo endereço final, em no máximo um salto:
for u in http://seusite.com.br http://www.seusite.com.br https://seusite.com.br https://www.seusite.com.br; do
echo "== $u"
curl -sSIL --max-redirs 20 "$u" | grep -iE '^(HTTP|location)'
done- Teste uma página interna e uma com parâmetro, como
/blog/e/produto?cor=azul. Regras de barra e de query string costumam escapar do teste da home. - Abra numa janela anônima, porque 301 e 308 ficam no cache do navegador.
- Limpe o cache da CDN se ela guardou a resposta de redirect.
- No Search Console, peça a validação do motivo Erro de redirecionamento.
O loop costuma voltar quando alguém liga uma opção sem saber da regra que já existia. A varredura grátis da Varrida segue os redirects das quatro entradas da home e de uma amostra das páginas do sitemap e mostra a cadeia de cada uma; no Pro, a checagem roda todo dia e a cada deploy, com aviso por e-mail e Slack quando piorar.

