Una redirección 301 en .htaccess es una línea:
Redirect 301 /old-page https://example.com/new-page
Guarda eso en el archivo .htaccess de tu raíz de documentos y queda activo de inmediato. Apache lee el archivo en cada petición, así que no hay reinicio ni despliegue. La directiva viene de mod_alias, que está presente en prácticamente todas las instalaciones de Apache, y envía un 301 Moved Permanently con un encabezado Location. Ese es todo el trabajo.
Casi todo lo que sale mal con las redirecciones de Apache ocurre después de este punto: recurrir a RewriteRule cuando Redirect bastaría, mezclar los dos módulos en un archivo y obtener un orden que nadie esperaba, o perder la cadena de consulta en el camino. Este artículo cubre las cuatro reglas que merece la pena memorizar, la trampa del orden de ejecución que hace que archivos con buena pinta se comporten mal, y cómo probar una redirección sin que tu navegador te mienta. Para el panorama más amplio de dónde pueden vivir las redirecciones, consulta cómo redirigir una URL.
La única línea que cubre la mayoría de las redirecciones
Redirect toma un estado, una ruta a la que coincidir, y un destino. El destino puede ser una URL completa o una ruta en el mismo host:
Redirect 301 /old-page /new-page
Redirect 301 /shop https://shop.example.com/
RedirectMatch 301 ^/blog/([0-9]{4})/(.*)$ /articles/$2
Vale la pena conocer dos comportamientos antes de usarlo. Primero, la propia guía de Apache es explícita en que esta es la herramienta correcta: "Este tipo de redirección simple de una URL, o de una clase de URLs, hacia otro lugar, debería lograrse usando estas directivas en lugar de RewriteRule."
Segundo, y este es el que sorprende a la gente: "Recuerda que Redirect conserva la información de la ruta. Es decir, una redirección para una URL /one también redirigirá todas las URLs debajo de ella, como /one/two.html y /one/three/four.html." Si solo quieres la ruta exacta, RedirectMatch 301 ^/one$ la fija. De lo contrario, acabas de redirigir un subárbol entero, lo que a veces es precisamente lo que querías y a veces es una mañana muy confusa.
RedirectMatch es la versión con expresiones regulares, y cubre la mayoría de los casos para los que la gente abre mod_rewrite. Los grupos capturados terminan en $1, $2, y así sucesivamente, así que un cambio de nombre de directorio o un cambio de esquema de URL basado en fechas es una sola línea.
Cuándo realmente necesitas RewriteRule
Recurre a mod_rewrite cuando la decisión depende de algo más que la ruta. El host, la cadena de consulta, el método de la petición, las cookies, y el user agent son todos visibles para RewriteCond e invisibles para Redirect:
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)ref=oldpartner(&|$)
RewriteRule ^landing$ /partners/oldpartner? [R=301,L]
Hay una trampa en el contexto por directorio que explica una gran parte de las reglas copiadas y pegadas que no hacen absolutamente nada. Apache elimina el prefijo del directorio antes de hacer coincidir, así que el patrón nunca ve una barra inicial: "El prefijo eliminado siempre termina con una barra, lo que significa que la coincidencia se produce contra una cadena que nunca tiene una barra inicial. Por lo tanto, un patrón con ^/ nunca coincide en el contexto por directorio."
Por eso RewriteRule ^/old$ /new [R=301] funciona cuando alguien lo pega en un host virtual y falla en silencio en .htaccess. Quita la barra: ^old$. Cuando tu sustitución es una ruta relativa y la reescritura vive en un subdirectorio, también puede que necesites RewriteBase para decirle a Apache respecto a qué son relativas las rutas.
La trampa del orden de ejecución
Esta es la que le cuesta a la gente una tarde entera. La posición de la línea en el archivo no decide qué módulo se ejecuta primero.
Apache lo documenta con claridad: "Si mezclas Redirect y RewriteRule en el mismo contexto, ten en cuenta que su orden de ejecución depende de dónde aparezcan. En el contexto de servidor/host virtual, mod_rewrite se ejecuta primero; en el contexto por directorio (.htaccess), mod_alias se ejecuta primero."
Lee eso dos veces, porque la consecuencia es contraintuitiva. En un archivo .htaccess, un Redirect al final del archivo gana a un RewriteRule al principio. Mueve las mismas reglas a un host virtual y el ganador se invierte. La bandera [L] tampoco te salva: significa última regla en este pase de mod_rewrite, no última regla del archivo, y no tiene autoridad sobre otro módulo.
La regla práctica que sigo: un módulo por archivo. Si un proyecto necesita condiciones en algún sitio, haz todas sus redirecciones con mod_rewrite y elimina las líneas de Redirect. Los archivos mezclados son de donde vienen los reportes de errores que dicen "la redirección funciona en staging pero no en producción", porque los dos entornos colocan las reglas en contextos diferentes.
Cadenas de consulta: conservadas, sustituidas o borradas
Los enlaces de marketing viven y mueren por sus cadenas de consulta, así que esta tabla merece la pena tenerla a la vista. Todo esto es comportamiento documentado, no folclore.
| Lo que escribes | Cadena de consulta original | Notas |
|---|---|---|
Redirect 301 /a /b | Se traslada | mod_alias la añade por ti |
RedirectMatch 301 ^/a$ /b | Se traslada | Mismo módulo, mismo comportamiento |
RewriteRule ^a$ /b [R=301] | Pasa sin cambios | El comportamiento predeterminado documentado |
RewriteRule ^a$ /b?src=x [R=301] | Sustituida por la tuya | Tus parámetros ganan |
RewriteRule ^a$ /b?src=x [R=301,QSA] | Combinada con la tuya | QSA añade la original |
RewriteRule ^a$ /b? [R=301] | Borrada | Un ? suelto la elimina |
La redacción de Apache sobre el comportamiento predeterminado: "Por defecto, la cadena de consulta pasa sin cambios." Y sobre las banderas, [QSA] "añade cualquier cadena de consulta de la URL de la petición original a cualquier cadena de consulta creada en el destino de la reescritura", mientras que [QSD] descarta la entrante. Si rediriges a una URI absoluta, la cadena de consulta te acompaña a menos que pidas [QSD].
El fallo que esto evita es silencioso y costoso. Una regla que sustituye la cadena de consulta elimina utm_source y utm_campaign en el camino, tu analítica atribuye la sesión a tráfico directo, y nada da error. Nadie se da cuenta hasta que alguien pregunta por qué la campaña de primavera no recibió ningún crédito. Los parámetros UTM no aparecen en GA4 cubre el diagnóstico desde el lado de la analítica.
Si te encuentras manteniendo decenas de redirecciones de campaña en un archivo de configuración del servidor, eso es una señal más que una tarea rutinaria. Las reglas de servidor necesitan un despliegue, una revisión de la configuración de Apache, y alguien con acceso por shell. Traslada los enlaces de campaña a enlaces cortos que puedas editar tú mismo y reserva .htaccess para las redirecciones estructurales en las que es bueno.
HTTPS y www en un salto, no en dos
El fragmento más copiado de internet hace esto en dos bloques de reglas, lo que significa que un visitante que llega a http://example.com/page es redirigido dos veces: una para añadir TLS, otra para añadir www. Dos saltos, dos viajes de ida y vuelta, y una señal un poco más débil en cada uno.
Una regla, dos condiciones, un salto:
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]
Detrás de una CDN o un balanceador de carga, %{HTTPS} suele estar en off en el origen incluso cuando el visitante está en HTTPS, porque el TLS terminó más arriba. Comprueba %{HTTP:X-Forwarded-Proto} en su lugar:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
Equivócate en esto y construirás un bucle de redirección infinito: el proxy envía HTTPS, el origen cree que es HTTP, redirige a HTTPS, y así da vueltas hasta que el navegador se rinde. Cómo arreglar un bucle de redirección explica cómo diagnosticar eso a partir de los encabezados de respuesta.
Por qué no está funcionando
En el orden en que las compruebo:
AllowOverrideestá enNone. La documentación de Apache indica el comportamiento predeterminado: "Esto significa que los archivos.htaccessse ignoran por completo a menos que los habilites explícitamente para un directorio." Pruébalo poniendo basura deliberada en la primera línea. Que no aparezca un error 500 significa que tu archivo no se está leyendo en absoluto, y cada regla en él es decoración.- El archivo está mal ubicado o mal nombrado. Debe ser
.htaccess, con el punto inicial, en el directorio al que se mapea la petición. Los editores que "amablemente" guardanhtaccess.txtson una causa recurrente. - mod_rewrite no está cargado.
Redirectfunciona,RewriteRulefalla en silencio, lo que hace que la gente se pase una hora mirando su expresión regular. - Tu navegador cacheó el 301 antiguo. Tanto Chrome como Firefox cachean las redirecciones permanentes de forma agresiva, por perfil de navegador, así que el arreglo que acabas de desplegar es invisible para ti y funciona perfectamente para todos los demás. Durante el desarrollo, usa
R=302y cambia aR=301cuando la regla esté correcta. - La regla coincide con su propio destino.
RewriteRule ^(.*)$ /index.php/$1sin protección es el caso clásico. Añade una condición que exima al destino.
Prueba con curl, no con el navegador
Un solo comando te dice el estado, el destino, y cuántos saltos tomó:
curl -sIL https://example.com/old-page | grep -iE '^HTTP|^location'
Lee la salida como una secuencia. Dos líneas HTTP/2 301 antes del 200 significa dos saltos, y cada salto es un viaje de ida y vuelta real para un visitante real en una red móvil. La documentación de Google sobre redirecciones trata una redirección permanente como la señal más fuerte para consolidar una URL, y llegar ahí en un paso es estrictamente mejor que llegar en tres. Nuestro comprobador de enlaces muestra la misma cadena en un navegador, y redirecciones 301 frente a 302 cubre qué estado enviar cuando no estás seguro.
Prueba las rutas que importan en lugar de la que acabas de escribir: la raíz, una ruta profunda, una ruta con cadena de consulta, y el propio destino. Esta última detecta bucles antes de que lo hagan tus visitantes.
Cuándo no usar .htaccess en absoluto
La propia postura de Apache es inequívoca. "Si tienes acceso al archivo de configuración principal del servidor, deberías poner toda tu configuración ahí en lugar de en archivos .htaccess," porque el análisis por petición cuesta trabajo real: "permitir archivos .htaccess provoca un impacto en el rendimiento, tanto si realmente los usas como si no." En hosting compartido no tienes elección. En un servidor que controlas, la configuración principal es el mejor hogar para cualquier cosa estructural.
Hay un segundo caso para mantener las reglas completamente fuera del archivo, y no tiene nada que ver con el rendimiento. Las redirecciones que aparecen en material impreso, en un código QR, o en la presentación de alguien más necesitan sobrevivir a tu servidor web, a la migración de tu CMS, y posiblemente a tu proveedor de hosting. Una regla en .htaccess está a un despliegue descuidado de distancia de desaparecer, y nadie reporta un enlace impreso muerto hasta que la campaña termina. Las redirecciones estructurales pertenecen al servidor; los enlaces de campaña e impresos pertenecen a un lugar que puedas editar en segundos y medir sin rastrear registros de acceso.
Lee la serie central
Este artículo pertenece al clúster de tutoriales. Para el mapa completo, tipos de redirecciones cubre todos los códigos de estado y los métodos del lado del cliente, y cómo redirigir una URL cubre los seis lugares donde puede vivir una redirección.
Relacionados en el blog
Preguntas frecuentes
¿Cómo creo una redirección 301 en .htaccess?
Pon una línea en el archivo .htaccess de tu raíz de documentos: Redirect 301 /old-page https://example.com/new-page. Apache lee .htaccess en cada petición, así que la redirección queda activa en el momento en que guardas el archivo. Sin reinicio, sin despliegue. Esa directiva viene de mod_alias, que está habilitado en prácticamente todas las instalaciones de Apache.
¿Cuál es la diferencia entre Redirect y RewriteRule?
Redirect y RedirectMatch vienen de mod_alias y hacen una sola cosa: enviar un código de estado y un encabezado Location. RewriteRule viene de mod_rewrite y puede inspeccionar el host, la cadena de consulta, las cookies, o el user agent antes de decidir. La propia documentación de Apache dice que la redirección simple debería usar mod_alias en lugar de RewriteRule, y trata mod_rewrite como último recurso.
¿Por qué no funciona mi redirección de .htaccess?
Cinco causas cubren casi todos los casos: AllowOverride está en None así que el archivo se ignora por completo, el archivo no está en la raíz de documentos o tiene un nombre incorrecto, mod_rewrite no está cargado, tu navegador cacheó un 301 anterior y nunca vuelve a preguntarle al servidor, o la regla coincide con su propio destino y crea un bucle. Prueba con curl en lugar de un navegador, porque un 301 cacheado hace que una regla ya corregida parezca rota.
¿Sobrevive la cadena de consulta a una redirección 301 en .htaccess?
Con Redirect y RedirectMatch, sí, se traslada automáticamente. Con RewriteRule, la respuesta depende de la sustitución: sin signo de interrogación en ella y la cadena de consulta original pasa a través, un signo de interrogación con tus propios parámetros la sustituye, un signo de interrogación suelto al final la borra, y el indicador QSA combina ambas. Equivocarse en esto elimina parámetros UTM sin avisar.
¿Cómo redirijo de HTTP a HTTPS y de non-www a www en un solo salto?
Usa una sola regla con dos condiciones unidas por OR, reescribiendo hacia el esquema y el host canónicos en un único paso. Dos bloques de reglas separados producen dos redirecciones para cualquiera que llegue por http:// sin www, y cada salto extra cuesta latencia y diluye la señal. Detrás de un proxy o una CDN, comprueba %{HTTP:X-Forwarded-Proto} en lugar de %{HTTPS} o construirás un bucle.
¿.htaccess ralentiza un sitio?
Ligeramente, e inevitablemente. La documentación de Apache es directa al respecto: permitir archivos .htaccess provoca un impacto en el rendimiento tanto si los usas como si no, porque httpd busca el archivo en cada directorio en cada petición. Si tienes acceso a la configuración principal del servidor, esas mismas reglas pertenecen ahí, cargadas una sola vez al arrancar.
Prueba Elido
Pega una URL, obtén un enlace corto
Sin registro. El enlace vive 30 días. Crea una cuenta para conservarlo.
Gratis, sin registro · 2 por día