Cuatro códigos de redirección HTTP, cuatro comportamientos significativamente distintos, y un error SEO consistente que aparece en cada migración: usar 302 como predeterminado porque es lo que emite el framework. Aquí está la matriz de decisión real para 301 vs 302 vs 307 vs 308, más el costo real de equivocarse.
Los cuatro códigos en una oración cada uno
301 Moved Permanently: la redirección permanente canónica. Almacenable en caché. El método puede cambiar de POST a GET. La predeterminada para movimientos de URL permanentes.
302 Found: redirección temporal. Almacenable en caché pero con revalidación. El método puede cambiar de POST a GET. Los frameworks lo usan como predeterminado; casi nunca es la opción correcta para movimientos permanentes SEO.
307 Temporary Redirect: como 302 pero se preserva el método. POST sigue siendo POST. Se usa para movimientos temporales donde el método importa (raro en SEO de sitios de marketing; común en APIs).
308 Permanent Redirect: como 301 pero se preserva el método. POST sigue siendo POST. El reemplazo de la era HTTP/2 para 301 cuando importa la preservación del método. Los frameworks modernos (Next.js, Vercel) emiten 308 por defecto para llamadas a redirect().
Por qué esto importa para SEO
Google ha declarado públicamente que 301 y 308 transfieren la señal completa de PageRank. 302 y 307 la transfieren de forma menos confiable — la interpretación que Google tiene baked in es que un redirect temporal apunta a un destino temporal, así que la señal canónica debe permanecer en la URL original. En una migración, esto es exactamente lo opuesto: quieres que la señal canónica se mueva.
Impacto en el mundo real: un sitio que implementa redirects de migración como 302 en lugar de 301 típicamente pierde entre 20-40% del tráfico orgánico en los primeros 60 días post-cutover. La solución no es sutil, pero tampoco siempre se detecta porque los 302s funcionan para los usuarios (el navegador los sigue, la página carga). Search Console marca el problema en el reporte de Coverage bajo "Page with redirect" pero la mayoría de los equipos ignoran ese reporte durante el pánico post-cutover.
La matriz de decisión
Tres preguntas. Respóndelas en orden; el resultado determina el código.
Pregunta 1: ¿Es el movimiento permanente?
Si sí (la URL se mueve para siempre, la URL antigua no volverá): usa 301 u 308. Si no (la URL volverá, esto es temporal): usa 302 o 307.
Pregunta 2: ¿La URL recibe solicitudes POST?
Si sí (envíos de formularios, llamadas a API, POSTs en JSON): usa 307 u 308 (método preservado). Si no (navegación del navegador, clic en enlace): 302 o 301 están bien.
Pregunta 3: ¿Cuál es el default del framework?
Stacks modernos: Next.js redirect() emite 308 por defecto, vercel.json [[redirects]] usa 308 a menos que se establezca permanent: false, Netlify _redirects usa 301 a menos que se indique explícitamente lo contrario. Apache mod_rewrite usa 302 por defecto, lo que atrapa a todos la primera vez. Siempre verifica el defecto de tu framework antes de confiar en él.
Los cuatro errores más comunes
- Usar 302 por defecto porque Apache/Express/Flask lo emiten como defecto para el helper redirect(). Solución: establece explícitamente 301 en cada regla de redirección en un movimiento permanente.
- Usar 307 pensando que es el 301 moderno. No lo es — 307 es el 302 moderno (temporal, que preserva el método). Para movimientos permanentes usa 308 o 301.
- Mezclar 301 y 302 en el mismo mapa de redirecciones. Elige uno (301 para migraciones) y úsalo en todas partes; códigos mixtos confunden el reporte de Search Console.
- Olvidar que 308 preserva el método POST. Si tu URL antigua era un endpoint de envío de formulario y la redireccionas con 308 a la nueva URL, los datos POST fluyen a través. Si usas 301, el navegador convierte POST a GET y el envío del formulario se pierde. Conocer la diferencia atrapa una clase real de bugs.
Cuándo usar cuál, en la práctica
Redirecciones de migración (dominio antiguo → dominio nuevo, slug antiguo → slug nuevo): usa 301. La más simple, más ampliamente soportada, y explícitamente indicada por Google como una transferencia completa de PageRank.
Movimientos permanentes donde la preservación del método importa (endpoints POST, envíos de formularios): usa 308. La transferencia de PageRank es idéntica a 301; la única diferencia es que POST se mantiene como POST.
Movimientos temporales (pruebas A/B, redirecciones geográficas, mantenimiento): usa 302. La transferencia de PageRank menor es el comportamiento correcto porque la URL de origen debería retener su señal de ranking.
Movimientos temporales con preservación de método (endpoints API bajo failover temporal): usa 307.
Cómo configurar cada código en plataformas comunes
Vercel (vercel.json)
Bloque [[redirects]]. Establece permanent: true para 308 (predeterminado), permanent: false para 307. Para forzar 301 usa statusCode: 301 explícitamente. La mayoría de los deploys modernos de Vercel usan 308 por defecto, lo cual está bien para migraciones; la opción conservadora en SEO es 301 para máxima compatibilidad con crawlers e indexadores más antiguos.
Netlify (netlify.toml o _redirects)
Sintaxis _redirects: /old-url /new-url 301 para permanente, /old-url /new-url 302 para temporal. Añade ! para forzar el estado: /old-url /new-url 301!.
Apache (.htaccess)
Redirect 301 /old-url /new-url para permanente. RewriteRule con flag [R=301,L] para redirects de tipo rewrite.
Nginx
return 301 https://example.com/new-url; dentro de un bloque location. Para coincidencia de patrones: rewrite ^/old/(.*)$ /new/$1 permanent; (el flag permanent emite 301; el flag redirect emite 302).
Verificar los códigos en producción
Tres comandos que todo ingeniero debe tener en la memoria muscular. curl -I https://example.com/old-url devuelve el código de estado en los encabezados de la respuesta. curl -ILk sigue redirecciones y registra cada código de estado en el camino (detecta cadenas).
Para verificación en masa en cientos de URLs, automatizable: un bucle fetch en Node.js que lee un CSV de URLs antiguas y registra el estado + destino final. O usa el endpoint Instant Pages de DataForSEO on-page, que devuelve el rastro completo de redirecciones.
El resumen
301 para movimientos permanentes (predeterminado para migraciones SEO). 308 cuando la preservación del método importa y el movimiento es permanente. 302 para movimientos temporales. 307 para movimientos temporales con preservación del método. Los valores predeterminados del framework no siempre son correctos; verifica durante el despliegue.
Lecturas relacionadas: 410 vs 404 cubre el caso de retiro (URLs que desaparecen para siempre, no que se mueven). La misma migración generalmente requiere ambas decisiones.