Redirecionamentos 301 no .htaccess para WordPress: o guia técnico

Redirecionamentos 301 no .htaccess para WordPress: o guia técnico

Última verificação: 15 de outubro de 2026
14 min de leitura
Guia
500+ projetos WP

Durante remodelações estruturais de sítios web, alterações de taxonomia em lojas WooCommerce ou migrações de domínio, a integridade do tráfego orgânico depende exclusivamente de um mapeamento rigoroso de redirecionamentos. Em servidores com pilha web Apache ou LiteSpeed, o ficheiro .htaccess é o mecanismo primário de reescrita de rotas.

Contudo, a configuração empírica do .htaccess com fragmentos de código retirados de discussões online costuma originar problemas graves: cadeias de redirecionamentos com múltiplos saltos, parâmetros de rastreio perdidos e trabalho extra do servidor web em cada pedido. Este artigo apresenta uma abordagem estruturada para programadores que necessitam de implementar regras limpas, seguras e de elevado desempenho.

#1. Como o bloco nativo do WordPress trata pedidos e redirecionamentos

Quando instala o WordPress e ativa a estrutura de ligações permanentes (Pretty Permalinks), o núcleo gera um bloco padrão no ficheiro .htaccess:

# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

#Porque é que as regras devem ficar antes do bloco WordPress

Se adicionar as suas regras personalizadas no final do ficheiro, após a linha # END WordPress, elas nunca serão executadas para páginas apagadas ou movidas.

A linha RewriteRule . /index.php [L] contém a flag [L] (Last). Quando um pedido para um endereço inexistente atinge esta instrução, o Apache entrega o pedido ao script index.php do WordPress e termina a passagem atual pelas regras. O WordPress assume então o pedido e gera uma página de erro 404, sem nunca consultar as regras situadas abaixo.

Regra mandatória: Qualquer regra de redirecionamento 301, reencaminhamento de domínio ou normalização canónica deve ser inserida estritamente antes do comentário # BEGIN WordPress.

Além disso, sempre que altera as definições de ligações permanentes no painel de administração, o WordPress reescreve por completo o conteúdo situado entre # BEGIN WordPress e # END WordPress, apagando qualquer instrução que tenha sido colocada inadvertidamente no interior desse espaço.

#2. Incompatibilidades entre mod_alias e mod_rewrite

O Apache dispõe de dois módulos para manipular caminhos de rede:

  • mod_alias: Controla as diretivas Redirect e RedirectMatch. É direto e eficiente para correspondências estáticas, mas compara apenas o caminho do URL e não tem acesso a variáveis avançadas do servidor nem a cadeias de consulta (query strings).
  • mod_rewrite: O motor completo de reescrita com suporte para expressões regulares, condições lógicas (RewriteCond) e flags de controlo de fluxo.

#Ordem de processamento entre mod_rewrite e mod_alias

Os dois módulos podem corresponder ao mesmo caminho. Qual deles atua primeiro é decidido pela forma como o Apache processa os módulos, não pela ordem visual das linhas no ficheiro .htaccess.

Considere o seguinte exemplo:

# Exemplo incorreto:
Redirect 301 /servico-antigo/ /servico-novo/
RewriteRule ^servico-antigo/(.*)$ /catalogo/$1 [R=301,L]

As duas linhas reclamam o mesmo endereço e enviam-no para destinos diferentes. Ler o ficheiro de cima para baixo não diz qual das respostas o visitante vai receber, e uma alteração posterior numa delas pode criar um ciclo de redirecionamentos.

Boa prática de engenharia: Use um só módulo para cada URL. Em projetos WordPress, onde o motor de reescrita já está ativo, manter todos os redirecionamentos em RewriteRule dá coerência ao ficheiro; para casos simples, a própria documentação do Apache prefere Redirect, como se explica mais abaixo.

#3. Como redirecionar páginas movidas 1:1 no .htaccess

Para páginas individuais que mudaram de endereço de forma permanente, deve isolar o início (^) e o fim ($) do caminho relativo com expressões regulares:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Redirecionar página única mantendo compatibilidade com barra final
RewriteRule ^sobre-nos/?$ /empresa/ [R=301,L]

# Redirecionar ficheiro com extensão legada para URL limpo
RewriteRule ^artigo-tecnico\.html$ /artigo-tecnico/ [R=301,L]
</IfModule>

A inclusão do padrão /? torna a regra insensível à presença ou ausência da barra final no pedido do utilizador. A flag [R=301] instrui o servidor a emitir o código de estado HTTP 301 Moved Permanently, que a Google usa como sinal de que o novo endereço deve ser o canónico.

#4. Como normalizar HTTPS e WWW no .htaccess

Um dos problemas mais comuns detetados em auditorias técnicas é a existência de cadeias com múltiplos redirecionamentos 301 sucessivos. Por exemplo:

  1. http://dominio.pt reencaminha para https://dominio.pt
  2. https://dominio.pt reencaminha para https://www.dominio.pt

Cada salto adicional acrescenta latência para o utilizador, como lembra o guia da Google sobre mudanças de sítio. Deve consolidar as duas verificações numa única avaliação lógica:

#Forçar HTTPS e prefixo www numa só regra

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Se não estiver em HTTPS OU se o domínio não começar por www
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^(.*)$ https://www.%1/$1 [R=301,L]
</IfModule>

#Forçar HTTPS e domínio sem www (naked domain)

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Se não estiver em HTTPS OU se o domínio contiver o prefixo www
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
</IfModule>

Em qualquer dos cenários, qualquer combinação de protocolo inseguro ou formato de anfitrião é resolvida num único salto direto para o endereço canónico final.

#5. Como gerir query strings em redirecionamentos .htaccess

A diretiva padrão RewriteRule avalia apenas o caminho textual do pedido (Request Path), ignorando os argumentos presentes após o ponto de interrogação (?).

Isto significa que a regra seguinte não funcionará:

# REGRA INEFICAZ:
RewriteRule ^detalhe\.php\?produto_id=40$ /novo-produto/ [R=301,L]

Para capturar e redirecionar endereços antigos que dependiam de parâmetros GET (típicos de plataformas legadas), é obrigatório recorrer à variável %{QUERY_STRING} através de RewriteCond:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Redirecionar URL antigo com parâmetro específico e descartar a query string
RewriteCond %{QUERY_STRING} (^|&)produto_id=40(&|$)
RewriteRule ^detalhe\.php$ /novo-produto/ [QSD,R=301,L]
</IfModule>

Os delimitadores (^|&) e (&|$) impedem que a condição apanhe também produto_id=400 ou outro_produto_id=40.

#Para que serve a flag QSD no .htaccess

A flag QSD existe desde o Apache 2.4.0 e garante que os parâmetros antigos são eliminados no destino. Sem esta flag, o Apache preserva a cadeia original e produz o endereço indesejado /novo-produto/?produto_id=40. Em configurações mais antigas, o mesmo efeito obtinha-se com um ponto de interrogação no fim do destino (/novo-produto/?), como indica a documentação das flags.

Caso pretenda preservar parâmetros legítimos de campanha ou paginação, utilize a flag QSA (Query String Append):

# Preservar parâmetros UTM ou filtros na mudança de taxonomia
RewriteRule ^antiga-categoria/(.*)$ /nova-categoria/$1 [QSA,R=301,L]

#6. Como fazer redirecionamento integral de domínio no .htaccess

Quando duas marcas se fundem ou um projeto transita para um novo domínio com preservação da estrutura interna de páginas, implementa-se o reencaminhamento global:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Encaminhar todo o tráfego de dominio-antigo.pt para dominio-novo.pt
RewriteCond %{HTTP_HOST} ^(?:www\.)?dominio-antigo\.pt$ [NC]
RewriteRule ^(.*)$ https://dominio-novo.pt/$1 [R=301,L]
</IfModule>

A variável $1 armazena a totalidade do caminho relativo após a barra inicial, mantendo intactas as referências a artigos, imagens e documentos.

#7. Quando mover redirecionamentos para fora do .htaccess

Embora o ficheiro .htaccess ofereça flexibilidade durante o desenvolvimento local, o seu funcionamento em produção acarreta um custo contínuo:

  1. A cada pedido de imagem, ficheiro de estilos ou fonte tipográfica, o servidor tem de verificar o sistema de ficheiros em busca de ficheiros .htaccess em todas as diretorias superiores. O tutorial do Apache dá o exemplo de um ficheiro em /www/htdocs/example, que obriga a quatro consultas adicionais ao sistema de ficheiros.
  2. O ficheiro é carregado de novo cada vez que um documento é pedido, por isso uma lista com centenas ou milhares de linhas é lida repetidamente.

#Alternativas ao .htaccess: VirtualHost, Nginx e CDN

  • Configuração no VirtualHost: Se dispõe de acesso ao ficheiro de configuração do Apache (httpd.conf ou ficheiros em sites-available), transfira as listas volumosas para o bloco do anfitrião virtual. A configuração principal é carregada uma vez no arranque, em vez de ser lida a cada pedido.
  • Mapeamento em Nginx: Em arquiteturas com Nginx como proxy inverso diante do Apache, estruture as listas através de blocos map na configuração do Nginx.
  • Redirecionamentos na CDN (Edge Redirects): Para sítios de comércio eletrónico de grande escala com milhares de URLs descontinuados, descarregue essa responsabilidade para a Cloudflare (Bulk Redirects). O pedido é respondido na borda da rede e nunca chega ao servidor de origem.

#Como testar e validar redirecionamentos .htaccess

Antes de disponibilizar novas regras em ambiente de produção, cumpra as seguintes etapas de segurança:

  1. Confirme que todas as instruções residem antes da linha # BEGIN WordPress.
  2. Verifique o código de estado e o destino de cada salto na linha de comandos: curl -ILs "https://dominio.pt/url-antigo/" | grep -E "HTTP|Location".
  3. Teste em navegadores anónimos ou com as ferramentas de desenvolvimento abertas com a opção Disable cache ativa, para não sofrer a interferência de respostas 301 gravadas localmente.

#Como resolver ciclos de redirecionamento no .htaccess

#O que provoca um ciclo de redirecionamento

  1. Referências circulares: a regra A redireciona para B e a regra B devolve o pedido para A.
  2. Conflito de protocolo: uma regra para HTTP choca com a regra que força HTTPS.
  3. Conflito de WWW: as regras com www e sem www anulam-se uma à outra.
  4. Conflito com o WordPress: os redirecionamentos de um plugin chocam com os do .htaccess.

#Registar o mod_rewrite para encontrar o ciclo

# Configuração do servidor ou do anfitrião virtual: LogLevel não é permitido no .htaccess
LogLevel alert rewrite:trace3

As diretivas RewriteLog e RewriteLogLevel foram removidas no Apache 2.4 e substituídas pela definição LogLevel por módulo (mod_rewrite). A mesma página avisa que níveis acima de trace2 tornam o servidor muito mais lento, por isso use-os só para depuração e remova a linha no fim. Para ver apenas as entradas de reescrita: tail -f error_log | fgrep '[rewrite:'.

#Como parar um ciclo de redirecionamento no .htaccess

# Evitar ciclos verificando se o pedido já foi redirecionado
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

# Tratamento explícito do protocolo para evitar ciclos
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

#Como a Google trata os redirecionamentos 301, 302, 307 e 308

A documentação da Google sobre redirecionamentos (Redirecionamentos e a Pesquisa Google) divide-os em dois grupos. Os redirecionamentos permanentes (301 e 308) são seguidos pelo Googlebot, e o processo de indexação usa-os como sinal de que o destino deve ser o canónico, pelo que é o novo URL que aparece nos resultados. Os temporários (302, 303 e 307) também são seguidos, mas não contam como sinal canónico, e o URL de origem costuma manter-se nos resultados. A Google ordena ainda os métodos pela fiabilidade com que os consegue interpretar: um redirecionamento do lado do servidor, como o do .htaccess, vem em primeiro lugar, à frente do meta refresh e do JavaScript.

Isto conta no .htaccess porque os dois módulos do Apache usam o código temporário por omissão. Redirect sem argumento de estado envia um 302 (mod_alias), e RewriteRule com a flag [R] simples também envia um 302 (flags do RewriteRule). Uma migração escrita com [R,L] em vez de [R=301,L] publica redirecionamentos temporários sem qualquer mensagem de erro.

As cadeias também têm limite. Os rastreadores da Google seguem até 10 saltos de redirecionamento por omissão (códigos de estado HTTP), e o guia de mudança de sítio pede, idealmente, não mais de 3 saltos e menos de 5 no máximo, porque cada salto acrescenta latência (mudanças de sítio com alteração de URL). O mesmo guia recomenda manter os redirecionamentos de uma migração durante o máximo de tempo possível, em geral pelo menos um ano.

#Porque é que um RewriteRule com barra inicial não funciona no .htaccess

A razão mais comum para uma regra copiada da configuração do servidor não fazer nada no .htaccess é a barra inicial. Em contexto por diretoria (.htaccess e <Directory>), o Apache retira o caminho da diretoria, até à barra final inclusive, antes de comparar o padrão. A documentação do mod_rewrite di-lo diretamente: a cadeia nunca tem barra inicial, por isso um padrão que começa por ^/ nunca corresponde em contexto por diretoria.

# Configuração do VirtualHost: corresponde a /pagina-antiga/
RewriteRule ^/pagina-antiga/$ /pagina-nova/ [R=301,L]

# .htaccess na raiz do documento: o mesmo redirecionamento
RewriteRule ^pagina-antiga/$ /pagina-nova/ [R=301,L]

O padrão também nunca vê o nome do anfitrião nem a query string. Para os testar, use um RewriteCond sobre %{HTTP_HOST} ou %{QUERY_STRING}, e recorra a %{REQUEST_URI} quando precisar do caminho completo. Duas definições do servidor decidem se as regras chegam a correr: a reescrita no .htaccess exige Options FollowSymLinks ou SymLinksIfOwnerMatch, e tanto RewriteRule como Redirect precisam de AllowOverride FileInfo. O tutorial do .htaccess do Apache sugere um teste rápido: escreva uma palavra sem sentido, como TestMe, no ficheiro e recarregue a página. Se não aparecer um erro 500, está em vigor AllowOverride None e o Apache ignora o ficheiro.

#Diferença entre as flags L e END no .htaccess

No .htaccess, [L] não significa “parar de vez”. A documentação das flags explica que, em contexto por diretoria, [L] termina a passagem atual pelas regras, mas o pedido reescrito pode ser processado de novo desde o início, o que pode causar ciclos. [END] interrompe todo o processamento de reescrita seguinte para esse pedido, e a documentação apresenta-a como a flag preferível para a maioria das regras por diretoria. Em contexto de servidor ou de anfitrião virtual, as duas comportam-se da mesma forma.

Três pormenores da mesma página explicam muitos redirecionamentos avariados:

  • [R] sem [L] passa o URL reescrito à regra seguinte, o que pode gerar avisos Invalid URI in request no registo de erros, por isso escreva [R=301,L].
  • Com um código fora do intervalo 300 a 399, por exemplo [R=410], a substituição é ignorada e o URL de destino nunca é enviado. [G] e [F] exprimem essa intenção com mais clareza.
  • [QSD] (Apache 2.4.0 e posterior) descarta a query string e, quando [QSD] e [QSA] aparecem juntas, prevalece [QSD].

#Quando o Apache recomenda Redirect em vez de RewriteRule

O guia da própria equipa do Apache, Quando não usar o mod_rewrite, chama ao mod_rewrite um último recurso e diz que redirecionamentos simples de um URL ou de uma classe de URLs devem usar Redirect ou RedirectMatch. Redirect mantém a informação de caminho, por isso Redirect "/one/" "http://one.example.com/" também move /one/two.html. Só corresponde a segmentos de caminho completos: /service não apanha /servicefoo.txt. Passa os parâmetros GET para o destino, e os corpos de pedidos POST são descartados (mod_alias).

Para um nome de anfitrião canónico, o mesmo guia usa um bloco <If> em vez de RewriteCond:

<If "req('Host') != 'www.example.com'">
    Redirect "/" "https://www.example.com/"
</If>

Refere também que o padrão de front-controller que o WordPress escreve no .htaccess (encaminhar todos os ficheiros e diretorias inexistentes para index.php) pode ser expresso com FallbackResource /index.php, que também funciona no .htaccess. Numa instalação WordPress, deixe o bloco gerado como está, porque o WordPress reescreve tudo entre # BEGIN WordPress e # END WordPress. A regra prática é manter um módulo por URL: não deixe que um Redirect e um RewriteRule correspondam ao mesmo caminho.

#Como usar RewriteMap para guardar milhares de redirecionamentos

Uma lista longa de redirecionamentos no .htaccess paga-se em cada pedido. Segundo o tutorial do .htaccess, quando os ficheiros .htaccess estão permitidos, o httpd procura-os em todas as diretorias e diretorias superiores e volta a carregar o ficheiro sempre que um documento é pedido, incluindo imagens, CSS e JavaScript. A mesma página recomenda a configuração principal do servidor sempre que tiver acesso a ela.

A resposta do Apache para mapeamentos grandes é o RewriteMap. Só pode ser declarado em contexto de servidor ou de anfitrião virtual, nunca no .htaccess (guia do RewriteMap). Um mapa em texto simples tem um par chave e valor por linha, separados por espaço, e o httpd guarda em cache as chaves consultadas até a data de modificação do ficheiro mudar. Um mapa dbm: criado com httxt2dbm é indexado, por isso as consultas são mais rápidas do que num ficheiro de texto:

# Configuração do VirtualHost, não .htaccess
RewriteEngine On
RewriteMap redirects "dbm:/etc/apache2/redirects.map"
RewriteCond "${redirects:%{REQUEST_URI}}" !=""
RewriteRule "^" "${redirects:%{REQUEST_URI}}" [R=301,L]
# redirects.txt: um par "caminho-antigo caminho-novo" por linha
# /pagina-antiga/ /pagina-nova/
httxt2dbm -i redirects.txt -o redirects.map

A condição ignora o redirecionamento quando o caminho não está no mapa, por isso os URLs sem correspondência seguem para o WordPress como de costume.

Se necessita de apoio profissional na orquestração de migrações complexas de catálogos WooCommerce ou otimização profunda de infraestrutura, conheça o nosso trabalho de consultoria e engenharia WordPress.

Próximo passo

Transforme o artigo numa implementação real

Este bloco reforça a ligação interna e conduz o leitor para o passo seguinte mais útil dentro da arquitetura do site.

Quer implementar isto no seu site?

Se o problema está nos Core Web Vitals, no rendering lento ou no peso do WordPress, posso mapear e implementar a otimização.

Explorar outros serviços WordPress e base de conhecimento

Reforce o seu negócio com suporte técnico profissional em áreas-chave do ecossistema WordPress.

Perguntas frequentes

Respostas práticas para aplicar o tema na execução real.

Qual é a localização correta para novas regras de redirecionamento no .htaccess do WordPress?#
Devem ser colocadas sempre antes do comentário # BEGIN WordPress. Abaixo dele, a regra do front-controller entrega os URLs inexistentes ao index.php e as regras seguintes nunca chegam a ser avaliadas para essas páginas.
Por que razão ocorrem erros ao misturar a diretiva Redirect com RewriteRule?#
As diretivas pertencem a módulos distintos do Apache (mod_alias e mod_rewrite) e ambas podem corresponder ao mesmo caminho. A ordem em que atuam é decidida pelo processamento dos módulos no Apache, não pela ordem das linhas no ficheiro, por isso o resultado é difícil de prever a partir da leitura do .htaccess. Use um só módulo para cada URL.
Como eliminar parâmetros antigos (como ?id=45) ao redirecionar para um novo URL?#
A partir do Apache 2.4.0, adicione a flag [QSD,R=301,L] à sua instrução RewriteRule. A flag QSD descarta a query string original. Em versões anteriores, colocava-se um ponto de interrogação no final do URL de destino, que tem o mesmo efeito.
Quantas regras de redirecionamento suporta o .htaccess sem prejudicar a velocidade?#
A documentação do Apache não indica um número. Explica que, com os ficheiros .htaccess permitidos, o servidor procura-os em cada diretoria e carrega o ficheiro a cada pedido, incluindo imagens, folhas de estilo e JavaScript, e recomenda a configuração principal sempre que houver acesso a ela. Para listas extensas, o Apache propõe o RewriteMap no VirtualHost; outra opção são os redirecionamentos na CDN.

Precisa de FAQ adaptado ao setor e mercado? Crio uma versão alinhada com os seus objetivos de negócio.

Fale connosco

Artigos Relacionados