Skip to content

Código de status HTTP · Redirecionamento (3xx)

301 Moved Permanently

O redirecionamento 301 (Moved Permanently) significa que o recurso agora mora na URL do cabeçalho Location e todos os próximos acessos devem ir para lá. É o jeito padrão de mudar uma página de endereço de vez, como ao trocar o slug, migrar de HTTP para HTTPS ou unificar o domínio com e sem www.

Dados sobre este código de status
Classe3xx, Redirecionamento
Definido emRFC 9110 §15.4.2
Pode ir para o cache por padrãoSim, de forma heurística; sem Cache-Control, navegadores costumam guardá-lo sem prazo
Pode repetir o pedidoSiga o Location agora e mande os próximos pedidos para a nova URL
Cabeçalhos relevantes
  • Location: a nova URL definitiva; caminhos relativos são resolvidos a partir da URL pedida
  • Cache-Control: use um max-age enquanto testa, para um redirecionamento errado não grudar no navegador

O que significa o 301

A RFC 9110, seção 15.4.2, diz que o 301 indica que o recurso ganhou uma nova URI permanente e que as referências futuras devem usá-la. O navegador segue o Location na hora e, como o 301 pode ser guardado em cache de forma heurística, Chrome e Firefox costumam lembrar dele sem prazo de validade. O visitante pode continuar sendo mandado para a URL nova pelo próprio cache muito depois de você apagar a regra no servidor.

A especificação também mantém uma herança antiga: o cliente pode transformar um POST em GET ao seguir um 301, e todos os navegadores principais fazem isso, descartando o corpo da requisição. Para formulários e endpoints de API que recebem POST, PUT ou DELETE, use o 308 Permanent Redirect, que mantém o método e o corpo.

Na documentação do Google, o 301 é um sinal forte de que o destino deve ser a URL canônica, então a URL nova substitui a antiga nos resultados de busca. Cadeias de redirecionamento continuam custando caro: os rastreadores do Google desistem depois de 10 saltos, e cada salto extra é mais uma ida e volta para quem está numa conexão lenta.

Quando usar

  • Uma página, produto ou artigo que mudou de URL definitivamente.
  • Forçar um único esquema e host canônicos: http para https, www para o domínio sem www ou o contrário.
  • Juntar URLs antigas depois de uma migração de site ou de uma mudança na estrutura de URLs do CMS.
  • Use para tráfego GET e HEAD; endpoints que recebem POST devem ganhar um 308.

Causas comuns

Se você está visitando o site

  • O navegador mostra "muitos redirecionamentos" (ERR_TOO_MANY_REDIRECTS) porque o site fica pulando entre http e https, ou entre www e sem www, em loop.
  • Um 301 antigo guardado no cache continua mandando você para um endereço que o site não usa mais.

Se você administra o servidor

  • Redirecionamento para HTTPS atrás de proxy ou CDN: a aplicação recebe HTTP puro vindo do proxy (o modo SSL Flexible da Cloudflare é o caso clássico), redireciona para https, e o proxy pede de novo por HTTP, para sempre.
  • Duas camadas discordam sobre o host canônico: o nginx manda o www para o domínio sem www e o CMS (a opção siteurl do WordPress, por exemplo) manda de volta para o www.
  • Cadeias que sobraram de várias migrações, como /a para /b para /c para https://www.exemplo.com/c, cada salto somando latência.
  • Um 301 usado para uma mudança que era temporária, agora guardado nos navegadores, o que impede reaproveitar a URL antiga com facilidade.
  • Requisições POST para um endpoint que mudou de lugar perdendo o corpo porque o cliente reenvia como GET.

Como resolver

Se você está visitando o site

  • Apague os cookies e os arquivos em cache do site (no Chrome: Configurações, Privacidade e segurança, Excluir dados de navegação, imagens e arquivos em cache); isso também remove 301 guardados.
  • Abra a página numa janela anônima: se carregar ali, o problema é um redirecionamento ou cookie antigo no seu perfil normal.

Se você administra o servidor

  • Rastreie cada salto com curl -sIL https://exemplo.com/pagina-antiga e aponte cada URL antiga direto para o destino final.
  • Atrás de proxy, decida o redirecionamento para https pelo X-Forwarded-Proto (ou mude a Cloudflare para SSL Full ou Full (strict)) em vez do esquema que a aplicação enxerga na conexão.
  • Aplique o host e o esquema canônicos em uma única camada, no servidor web ou na aplicação, nunca nas duas.
  • Enquanto testa uma regra nova, use 302 ou adicione Cache-Control: max-age=3600 ao 301, para um erro não ficar morando no navegador dos visitantes.
  • Troque para 308 nos endpoints redirecionados que recebem POST, PUT, PATCH ou DELETE.

Como enviar um 301

Express (Node.js)
app.get('/blog/:slug', (req, res) => {
  res.redirect(301, `/articles/${req.params.slug}`);
});
Next.js App Router (route handler)
// app/blog/[slug]/route.ts
export async function GET(
  request: Request,
  { params }: { params: Promise<{ slug: string }> }
) {
  const { slug } = await params;
  // Response.redirect needs an absolute URL
  return Response.redirect(new URL(`/articles/${slug}`, request.url), 301);
}

// next.config.js: permanent: true sends 308; ask for 301 explicitly
// redirects: async () => [
//   { source: '/blog/:slug', destination: '/articles/:slug', statusCode: 301 }
// ]
Go net/http
mux.HandleFunc("GET /blog/{slug}", func(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "/articles/"+r.PathValue("slug"), http.StatusMovedPermanently) // 301
})
Python FastAPI
from fastapi import FastAPI
from fastapi.responses import RedirectResponse

app = FastAPI()

@app.get("/blog/{slug}")
def old_blog_post(slug: str):
    # RedirectResponse defaults to 307; say 301 explicitly
    return RedirectResponse(f"/articles/{slug}", status_code=301)
Nginx
# http:// and www. both go to https://example.com, in one hop
server {
  listen 80;
  server_name example.com www.example.com;
  return 301 https://example.com$request_uri;
}

# A single moved page
location = /old-pricing {
  return 301 /pricing;
}

Costuma ser confundido com

301 vs 308
Os dois são permanentes e o Google trata igual; o 308 proíbe trocar POST por GET, enquanto o 301 permite e os navegadores trocam.
301 vs 302
O 302 é temporário: o navegador não guarda em cache por padrão e os buscadores mantêm a URL original no índice.
301 vs 410
Use 410 Gone quando não existe página substituta; um 301 para uma página sem relação, como a home, é tratado pelo Google como soft 404.

Perguntas frequentes

O redirecionamento 301 passa a autoridade de SEO para a nova URL?
O Google descreve o 301 como um sinal forte de que o destino deve ser a URL canônica, então a página nova assume o lugar da antiga nos resultados, junto com os sinais dela. Mantenha o redirecionamento enquanto a URL antiga ainda receber links ou visitas, de preferência por um ano ou mais.
Por quanto tempo o navegador guarda um 301 em cache?
Sem Cache-Control ou Expires, o 301 pode ficar em cache sem limite definido, e na prática Chrome e Firefox o mantêm até o cache ser limpo. Se existe chance de desfazer o redirecionamento, envie Cache-Control com um max-age que você aceite esperar.
Devo usar 301 ou 308?
Para páginas comuns acessadas com GET, os dois funcionam igual e o Google trata igual. Use 308 quando a URL redirecionada recebe POST, PUT ou DELETE, porque o 301 deixa o cliente transformar esses pedidos em GET e perder o corpo.
Como resolver ERR_TOO_MANY_REDIRECTS depois de criar um 301?
Rode curl -sIL na URL para enxergar o loop. Quase sempre são duas regras se desfazendo: um redirecionamento para https atrás de um proxy que fala com a origem por HTTP, ou regras de host no servidor e no CMS apontando em direções opostas.

Revisado em por Arielton Oberek.