Redirección .htaccess: escribir una redirección 301 o 302 en Apache

Cómo escribir una redirección 301 o 302 en el archivo .htaccess, qué directiva elegir (Redirect, RedirectMatch o RewriteRule) y los casos más comunes: cambio de dominio, HTTPS, página de inicio, WordPress.

Redirección .htaccess: escribir una redirección 301 o 302 en Apache

El archivo .htaccess permite redirigir una URL directamente en un servidor Apache, sin tocar la configuración principal. Aquí verá cómo escribir en él una redirección 301 o 302, qué directiva elegir (Redirect, RedirectMatch o RewriteRule) y cómo resolver los casos más comunes: cambio de dominio, forzar HTTPS, nueva página de inicio y WordPress.

ℹ️

Antes de empezar

El .htaccess no es el único lugar posible: el vhost es más rápido y un plugin del CMS más fácil de mantener. Para elegir, lea nuestro artículo .htaccess, vhost o plugin: ¿dónde colocar el plan de redirección?

Requisitos: el archivo .htaccess y los módulos de Apache

El archivo se coloca en la raíz del sitio (la carpeta que contiene la página de inicio), o en una subcarpeta para actuar solo sobre ese directorio. Es un archivo oculto: active la visualización de archivos ocultos en su cliente FTP o en el gestor de archivos de su alojamiento. Si no existe, cree un simple archivo de texto llamado .htaccess.

Dos módulos de Apache hacen este trabajo:

  • mod_alias, que aporta las directivas Redirect, RedirectPermanent y RedirectMatch;
  • mod_rewrite, que aporta RewriteEngine, RewriteCond y RewriteRule, para los casos condicionales.

Para que Apache lo lea, la configuración del servidor debe autorizar estas directivas (AllowOverride All, o al menos FileInfo). Con AllowOverride None, el archivo se ignora. En un alojamiento compartido casi siempre está ya autorizado. Nginx no tiene .htaccess: todo va en el bloque server.

Redirección 301 o 302: ¿permanente o temporal?

Una 301 indica que la página se ha movido de forma permanente: los motores de búsqueda saben que la dirección ha cambiado para siempre, y Google transfiere su valor SEO y sus enlaces al destino. Úsela para una migración, un cambio de dominio o una página renombrada.

Una 302 indica un traslado temporal: la dirección de origen sigue indexada, porque debe volver. Sirve para un mantenimiento, una promoción limitada en el tiempo o una prueba. Una 302 que se mantiene durante meses acaba tratada como una 301, pero es mejor ser explícito desde el principio.

Redirect y RedirectPermanent: la redirección simple

Para enviar una página a otra basta con Redirect. La directiva recibe el código, la ruta antigua (sin el dominio) y la dirección completa de destino:

Redirect 301 /pagina-antigua.html https://www.misitio.es/pagina-nueva/
RedirectPermanent /carpeta-antigua/ https://www.misitio.es/carpeta-nueva/
Redirect 302 /promo https://www.misitio.es/rebajas/

RedirectPermanent es un atajo de Redirect 301, y RedirectTemp de Redirect 302. Atención: Redirect actúa sobre un prefijo. La segunda línea también envía /carpeta-antigua/pagina.html a /carpeta-nueva/pagina.html: práctico para un directorio entero, pero puede sorprender.

RedirectMatch: redirigir con una expresión regular

RedirectMatch funciona como Redirect, pero con una expresión regular. Trata toda una familia de direcciones en una sola línea, reutilizando las partes capturadas con $1, $2, etc.:

# Antiguas páginas .php hacia direcciones sin extensión
RedirectMatch 301 ^/blog/(.*)\.php$ https://www.misitio.es/blog/$1

# Una sola URL exacta (^ y $ evitan el efecto prefijo)
RedirectMatch 301 ^/contacto\.html$ https://www.misitio.es/contacto/

RewriteRule y RewriteCond: las redirecciones avanzadas

Este módulo es el más flexible: cada regla puede depender de condiciones sobre el nombre de host, el protocolo, los parámetros o cualquier variable del servidor. El motor se activa una sola vez, al principio del archivo, con RewriteEngine On.

RewriteEngine On

# Una página concreta, descartando la cadena de consulta
RewriteRule ^pagina-antigua/?$ https://www.misitio.es/pagina-nueva/ [R=301,L,NC,QSD]

# Una URL con parámetro: /producto.php?id=12
RewriteCond %{QUERY_STRING} ^id=12$
RewriteRule ^producto\.php$ https://www.misitio.es/productos/silla/ [R=301,L,QSD]

Los indicadores entre corchetes cambian su comportamiento:

  • R=301 o R=302: el código HTTP devuelto (sin R, es una reescritura interna que el visitante no ve);
  • L: última regla, Apache se detiene ahí;
  • NC: no distingue mayúsculas y minúsculas;
  • QSD: descarta la cadena de consulta original (Apache 2.4); QSA la conserva añadiéndola.

En el .htaccess, el patrón comprobado no empieza por una barra: se escribe ^pagina-antigua, no ^/pagina-antigua. Es el error más frecuente al copiar un ejemplo escrito para un vhost.

¿Qué directiva usar?

NecesidadDirectiva
Una página hacia otraRedirect 301
Un directorio entero, con sus subpáginasRedirect 301 (efecto prefijo)
Una familia de direcciones según un patrónRedirectMatch 301
Según el host, el protocolo o un parámetroRewriteCond + RewriteRule
Un CMS que ya reescribe sus URL (WordPress, PrestaShop)RewriteRule

Evite mezclar los dos módulos para las mismas direcciones: mod_rewrite se ejecuta antes que mod_alias, sea cual sea el orden de las líneas, lo que da resultados difíciles de prever. En un sitio que ya usa mod_rewrite, escríbalo todo con el mismo módulo.

Redirigir un dominio entero con el .htaccess

En un cambio de dominio, coloque estas líneas en el sitio antiguo, bajo la línea RewriteEngine On. Cada dirección va a la misma página del nuevo dominio, ruta incluida:

RewriteCond %{HTTP_HOST} ^(www\.)?dominio-antiguo\.es$ [NC]
RewriteRule ^(.*)$ https://www.dominio-nuevo.es/$1 [R=301,L]

Esta regla global solo basta si las rutas se han mantenido. Si las URL han cambiado, hace falta un plan de redirección página a página, colocado antes de esta regla general. Recuerde también renovar el antiguo nombre de dominio: sin él, ninguna de estas redirecciones funciona.

Forzar HTTPS (y www) en el .htaccess

Para enviar todo el tráfico HTTP a HTTPS, y la versión sin www a la versión con www, en un solo salto:

RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.misitio.es/$1 [R=301,L]

Detrás de un proxy o un CDN (Cloudflare, balanceador de carga), %{HTTPS} vale siempre off y la regla entra en bucle: compruebe en su lugar la cabecera %{HTTP:X-Forwarded-Proto}.

Cambiar la página de inicio con el .htaccess

Para que otro archivo sirva de página de inicio no hace falta una redirección, sino la directiva DirectoryIndex. Apache sirve el primer archivo que encuentra en la lista, sin cambiar la dirección mostrada:

DirectoryIndex inicio.html index.php index.html

Si la página de inicio debe cambiar realmente de dirección (por ejemplo / hacia /es/), limite la redirección a la raíz, con RedirectMatch 301 ^/$ https://www.misitio.es/es/. Sin ^/$, todas las páginas irían a ese destino.

Redirección 301 en el .htaccess de WordPress

WordPress escribe sus propias reglas entre las líneas # BEGIN WordPress y # END WordPress, y las reescribe cada vez que cambian los enlaces permanentes. Coloque siempre sus líneas encima de ese bloque: debajo, WordPress capta la petición antes, y dentro, se borrarían. Un plugin en el menú de administración también es posible, pero carga PHP en cada visita.

# Redirecciones SEO
RewriteEngine On
RewriteRule ^articulo-antiguo/?$ https://www.misitio.es/articulo-nuevo/ [R=301,L]

# BEGIN WordPress
...
# END WordPress

Anular una redirección sin borrar las demás reglas

  1. Haga una copia de seguridad del archivo .htaccess antes de cualquier cambio.
  2. Ábralo con un editor de texto y busque la línea de la redirección (Redirect, RedirectMatch o RewriteRule, con sus posibles RewriteCond justo encima).
  3. Borre esas líneas, o coméntelas con un # al principio para conservar un rastro.
  4. Guarde y vuelva a subir el archivo al servidor.
  5. Pruebe en una ventana privada: los navegadores guardan en caché una 301 y pueden seguir aplicándola después de borrarla.

Probar una redirección .htaccess

Lo más fiable es leer las cabeceras HTTP del servidor, sin la caché del navegador. En la línea de comandos, curl -I https://www.misitio.es/pagina-antigua/ debe mostrar el estado 301 y una cabecera Location con la nueva URL. Compruebe también que solo hay un salto: una cadena (HTTP a HTTPS, luego a www, luego a la página final) ralentiza a los robots y diluye la señal. Un error 500 justo después de guardar indica un error de sintaxis: restaure la copia.

Para una migración de varios cientos de páginas, Swan genera las reglas para el .htaccess o el vhost, y prueba automáticamente cada dirección antigua.

<p><code>Redirect</code> (mod_alias) envía sencillamente una ruta a una dirección. <code>RewriteRule</code> (mod_rewrite) acepta expresiones regulares y condiciones sobre el dominio, el protocolo o los parámetros. Para una sola página basta con <code>Redirect 301</code>.</p>
<p>Las causas más frecuentes: un servidor que ignora el archivo, una barra de más al principio del patrón, una regla colocada bajo el bloque de WordPress o una antigua 301 guardada en la caché del navegador.</p>
<p>No hay límite técnico, pero Apache relee el archivo entero en cada petición. A partir de unos miles de líneas, coloque mejor el plan en el vhost.</p>

Swan genera su plan de redirección para el .htaccess o el vhost y comprueba cada URL.

La lista de verificación de migración SEO, en PDF. 20 páginas de controles que marcar, desde la decisión de migrar hasta el seguimiento tras la puesta en producción.

Para seguir leyendo

Todos los artículos