developer

Types of URL Redirects Explained (301, 302, 307, 308, Meta, JS)

The complete guide to URL redirect types: 301, 302, 303, 307, 308, meta refresh, and JavaScript. When to use each, SEO impact, and how to check them.

Team U2L 21 min read

Ask three developers which redirect to use and you'll get four opinions. That's because there are more types of URL redirects than most people realize: the HTTP spec ships with five different 3xx status codes, plus two client-side alternatives that redirect through HTML and JavaScript instead. Most of the confusion isn't about what each one does, but when the difference actually matters and when it's noise.

Pick the wrong redirect and the failure modes are quiet: a browser cache that won't let you undo a mistake, a POST that mysteriously turns into a GET, a page that Google keeps indexed at the wrong URL for months. None of it breaks in ways your monitoring picks up. It just slowly makes your migration or campaign underperform.

This guide walks through every redirect type you can realistically use in 2026: the five HTTP status codes (301, 302, 303, 307, 308), meta refresh, and JavaScript redirects. For each one, you'll get a plain definition, the exact scenario where it's the right choice, the failure modes to avoid, and the SEO implications. There's also a decision table at the end, code samples for the major stacks, and a quick way to check what redirect type any URL is actually returning.

The main types of URL redirects are five HTTP status codes and two client-side techniques. Permanent redirects: 301 (Moved Permanently) and 308 (Permanent Redirect, method-preserving). Temporary redirects: 302 (Found), 303 (See Other, forces GET), and 307 (Temporary Redirect, method-preserving). Client-side redirects: HTML meta refresh and JavaScript window.location. Server-side HTTP redirects are the strongest signal for both browsers and search engines.

Table of Contents

The Two Families of Redirects

Every redirect on the web falls into one of two buckets: server-side (an HTTP status code in the response header) or client-side (HTML or JavaScript in the response body that tells the browser to navigate somewhere else). The difference matters more than most people realize.

A server-side redirect is decided before a single byte of HTML reaches the browser. The origin server, a reverse proxy, or an edge worker sees the incoming URL, returns a 3xx status code with a Location header, and the browser follows the pointer. Search engine crawlers understand this immediately, browsers follow it deterministically, and there's no window during which the wrong URL is briefly visible.

A client-side redirect runs after the browser has already downloaded a full HTML document. The user sees a blank page (or the "redirecting…" placeholder some devs leave in), then the browser reads a meta tag or runs a script and navigates away. Search engines have to render the page to see it. Slow connections show the intermediate page for a beat. It works, but it's an inferior signal in almost every way.

Rule of thumb: if you control the server (or a proxy in front of it), always prefer a server-side redirect. Save meta refresh and JavaScript for the cases where you truly cannot touch the response headers. The rest of this article walks through each type in that order: HTTP redirects first, then the client-side alternatives.

301 Moved Permanently

A 301 redirect is an HTTP status code that signals a resource has been permanently moved to a new URL. Browsers cache the redirect aggressively, and search engines treat the new URL as the canonical version, transferring the original URL's ranking signals to the destination.

301 is the default answer for permanent moves. Site migrations, HTTP to HTTPS upgrades, www to non-www consolidation, retiring an old domain, moving a blog post to a new URL, cleaning up duplicate pages. If the old URL is gone for good, 301 is the code.

Two things make 301 special. First, browsers cache it, often indefinitely and without an expiration header. Once a browser has seen a 301, it may never request the original URL again for that user. That makes repeat visits fast, but it also means a 301 committed by mistake is hard to reverse; users have to clear cache or you have to wait months for organic churn. Second, search engines consolidate ranking signals from the old URL onto the destination, treating the new URL as canonical.

One subtlety worth knowing: 301 does not strictly preserve the HTTP method. Historically, some clients converted a POST to a GET when following a 301. Modern browsers usually preserve the method, but the spec doesn't require it. For API endpoints or anywhere method preservation matters, use 308 instead (covered below).

We've written a deeper piece on the permanent versus temporary redirect decision if you want to see the SEO tradeoffs unpacked in full.

302 Found (Temporary)

A 302 redirect signals that a resource has been temporarily moved. Browsers do not cache the redirect by default, and search engines keep the original URL in their index because the move is expected to be reversed.

Use 302 when the destination is genuinely situational: A/B tests where /pricing bounces to a variant for two weeks, a homepage promo pointing at a seasonal landing page, geo or device routing where /download sends iOS traffic to the App Store and Android traffic to Google Play, a maintenance page during a deploy, or an out-of-stock product temporarily forwarded to a parent category.

The persistent SEO myth that "302 loses PageRank" is folklore from a pre-2016 era. Google's Gary Illyes confirmed years ago that 30x redirects don't lose PageRank, and John Mueller has restated that long-running 302s are treated the same as 301s by Google's canonicalization system. Both codes flow link equity to the destination. What differs is intent: 302 keeps the original URL in the index, 301 replaces it.

Original spec quirk: 302 was named "Moved Temporarily" in HTTP/1.0 and renamed "Found" in HTTP/1.1 because implementations diverged on whether the request method should be preserved. That ambiguity is exactly why 307 exists.

303 See Other

A 303 See Other redirect tells the client to fetch a different URL using the GET method, regardless of the original request method. It exists specifically to prevent duplicate form submissions when a user refreshes the page after a POST.

303 is the redirect you use after processing a form. It's the backbone of the Post/Redirect/Get (PRG) pattern that every web framework since the early 2000s has recommended. A user submits a form via POST, your server processes it (creates the record, charges the card, whatever), and you respond with 303 See Other pointing at a confirmation page. The browser fetches the confirmation URL with GET, and if the user hits refresh, they refresh the confirmation page, not the original POST.

Without 303, refreshing after a form submission triggers the browser's "Confirm form resubmission" warning, and if the user clicks through, they submit the form again. Duplicate charges, duplicate signups, duplicate database rows. Almost every "I got double-billed" support ticket a small SaaS company has ever seen traces back to a missing 303 in a checkout flow.

303 explicitly changes the method to GET no matter what the original was. That's the point. If you need a temporary redirect that preserves the method (say, a POST that should stay a POST), use 307 instead.

For SEO purposes, 303 behaves like a temporary redirect: the original URL stays in the index. In practice, POST endpoints almost never get indexed anyway, so the SEO implications of 303 rarely come up.

307 Temporary Redirect

A 307 Temporary Redirect is the strict, method-preserving version of 302. It tells the client to repeat the request at a new URL using the exact same HTTP method and request body as the original.

307 exists because 302 was ambiguous about method preservation. Some browsers converted POST to GET on a 302 follow; others didn't. The result was subtle breakage in API redirects and form-heavy applications. 307 fixed that by explicitly forbidding the conversion.

Use 307 whenever you'd reach for 302 but the request method actually matters. Common cases: an API endpoint that accepts POST and moves temporarily to a different backend, a form submission URL that's been relocated during a partial rollout, or any RESTful service that needs to preserve PUT and DELETE methods across the redirect.

For SEO, 307 and 302 are functionally identical. Google treats both as temporary and keeps the original URL as canonical. The difference is purely technical: 307 is stricter, 302 is loose. If you're building HTTP APIs, prefer 307. If you're redirecting HTML pages, either works.

Web servers that emit 307 explicitly rather than defaulting to 302 tend to be modern proxies (Cloudflare Workers, Vercel edge functions, Nginx return 307) or frameworks that opted for spec-strict behavior. It's an increasingly common pick as more traffic flows through APIs instead of just page loads.

308 Permanent Redirect

A 308 Permanent Redirect is the strict, method-preserving version of 301. It signals a permanent move and enforces that clients repeat the request with the same method and body as the original.

308 is to 301 what 307 is to 302: the modern, stricter version that guarantees the client won't downgrade a POST to a GET when following the redirect. If you're building HTTP APIs and something moves permanently, 308 is the correct code.

For content pages, the difference between 301 and 308 rarely matters. GET requests to HTML pages behave the same either way, and Google explicitly treats 301 and 308 as equivalent for indexing purposes. The choice is a technical correctness call, not an SEO one.

One practical note: some CDN and hosting platforms don't emit 308 by default. If you configure a "permanent redirect" in Cloudflare Rules, Vercel vercel.json, or Netlify _redirects, check what code actually appears in the response header. Several platforms use 301 under a "permanent" label, which is fine for content but wrong for API endpoints where method preservation matters.

Meta Refresh Redirects

A meta refresh is an HTML tag that instructs the browser to reload the current page or navigate to a different URL after a specified delay. It's a client-side redirect implemented in the document's <head>, not in the HTTP response header.

The syntax looks like this:

<!-- Instant redirect (interpreted as permanent) -->
<meta http-equiv="refresh" content="0; url=https://example.com/new-page">

<!-- Delayed redirect (interpreted as temporary) -->
<meta http-equiv="refresh" content="5; url=https://example.com/promo">

Google actually handles meta refreshes reasonably well. Their official position is that instant meta refreshes (delay of 0) are treated similar to 301 redirects, and delayed meta refreshes (any positive delay) are treated more like 302s. That's more forgiving than the SEO folklore suggests.

Still, Google recommends against meta refreshes in almost every case. The reasons are practical: users see a flash of the intermediate page, screen readers announce the wrong URL first, the redirect fails entirely if JavaScript-heavy rendering doesn't complete in time on flaky mobile connections, and the URL bar briefly shows the wrong address. Server-side redirects avoid all of that.

The one legitimate use case for meta refresh is when you truly cannot control the HTTP response headers. Static site hosts that only serve pre-rendered HTML, some CMS platforms that don't expose redirect configuration, or legacy pages you can only edit in the source. In every other case, prefer an HTTP redirect.

JavaScript Redirects

A JavaScript redirect navigates the browser to a different URL by executing code that changes window.location. Like meta refresh, it's a client-side redirect that runs after the page loads.

The common implementations:

<script>
  // Simple redirect (goes into browser history)
  window.location.href = 'https://example.com/new-page';

  // Replace redirect (does not add to history - back button skips it)
  window.location.replace('https://example.com/new-page');
</script>

window.location.replace() is usually the right choice because it doesn't add the intermediate URL to browser history, so the back button doesn't trap the user in a redirect loop. window.location.href adds a history entry, which is annoying but occasionally what you want.

Google can follow JavaScript redirects, but it's the weakest option of the three. Rendering has to succeed, the script has to execute, and Googlebot has to allocate resources to render the page in the first place. All three of those can fail in ways that server-side redirects never can. Google's own guidance is that JavaScript redirects should only be used when neither server-side nor meta refresh is possible.

Where JavaScript redirects genuinely earn their keep is for conditional logic that a server can't easily replicate on the edge: routing based on user-agent quirks, sending logged-in versus logged-out users to different destinations after client-side auth state loads, or handling deep-linking fallbacks where you check whether an app is installed before deciding where to send the user. In pure "URL A goes to URL B" cases, they're the wrong tool.

Redirect Types Compared at a Glance

Redirect Type Persistence Method Preserved Cached SEO Signal Best For
301 Moved Permanently HTTP Permanent Loose Yes (aggressive) Passes equity, replaces canonical Site migrations, HTTPS, domain moves
302 Found HTTP Temporary Loose No Passes equity, keeps original canonical A/B tests, promos, maintenance
303 See Other HTTP N/A Forces GET No Rarely indexed After POST (PRG pattern)
307 Temporary Redirect HTTP Temporary Strict No Same as 302 Temporarily relocated APIs
308 Permanent Redirect HTTP Permanent Strict Yes Same as 301 Permanently relocated APIs
Meta Refresh (0 sec) HTML Permanent-ish GET only Weak Treated similar to 301 Static hosts with no header access
Meta Refresh (delayed) HTML Temporary-ish GET only No Treated similar to 302 "You will be redirected in 5 seconds" pages
JavaScript Redirect JS Depends GET only No Fragile, needs rendering Client-side conditional routing

Two columns worth lingering on. Method preservation is invisible until it isn't; if you're building APIs, ignoring it is how POST bodies quietly vanish. Cached is why 301s are so hard to undo: a 301 that lands in a user's browser cache may never re-request the original URL for that user, ever. Both are the kind of thing you learn by getting bitten once.

Which Redirect Should You Use?

The full decision tree in one page:

  1. Is the move permanent?

    • Yes, and it's an HTML page → 301
    • Yes, and it's an API endpoint (method matters) → 308
    • No → keep reading
  2. Is the redirect temporary?

    • Yes, and it's an HTML page → 302
    • Yes, and it's an API endpoint (method matters) → 307
    • No → keep reading
  3. Are you redirecting after a form POST to prevent duplicate submissions?

    • Yes → 303
  4. Can you not touch HTTP headers on this host?

    • Yes → meta refresh (0-second delay for permanent, positive delay for temporary)
    • You can, but you need conditional client-side logic → JavaScript redirect

For 90% of real-world use cases the answer is 301 (permanent HTML) or 302 (temporary HTML). Everything else is edge cases, but the edge cases matter when you hit them.

How to Check What Redirect a URL Is Using

Three fast ways to inspect what a URL is actually returning.

Browser DevTools. Open the Network tab, paste the URL, hit enter, and look at the Status column. You'll see the redirect status code on the first request and 200 on the destination. Check the "Preserve log" box if you're redirecting between origins so the initial request doesn't get cleared.

curl. Run this from a terminal:

curl -I https://example.com/old-page

The response header shows the status line (HTTP/2 301), the Location: header pointing at the destination, and any relevant caching directives. Add -L to follow the chain end to end and see every hop.

Online redirect checkers. Tools like httpstatus.io, redirect-checker.org, and Screaming Frog's SEO Spider walk the full chain in one click. Useful for spotting hidden chains, mixed-code redirects (say, a 301 that lands on a 302 that lands on a 200), and any hop that's returning the wrong status.

For meta refreshes and JavaScript redirects, none of the above will pick them up directly because they're not in the response headers. Use "View Source" on the destination page or check the DOM in DevTools to find them. This is one of the reasons server-side redirects are easier to audit at scale.

Common Redirect Mistakes

The failure modes we see repeatedly:

  1. Trusting framework defaults. Older versions of mod_rewrite default to 302 if you don't specify a code. Stock Express's res.redirect() defaults to 302. Always pass the status code explicitly.
  2. Redirect chains. A → B → C → D when A → D would work. Chains slow down crawlers, increase timeout risk, and burn crawl budget. Point each old URL at its final destination.
  3. Redirect loops. A redirects to B, B redirects back to A. Browsers detect and abort these, but they still waste user time and are almost always accidental.
  4. Soft 404s. Redirecting every removed page to your homepage instead of returning an honest 404 or a targeted redirect to a relevant page. Google explicitly flags these as low-quality.
  5. Forgetting query strings. /?utm_source=email doesn't always carry through a redirect unless you configure it to. Test campaign links with parameters before launch.
  6. Method downgrade on APIs. Using 301 or 302 on an API endpoint that accepts POST, then wondering why request bodies vanish. Use 308 or 307 for anything method-sensitive.
  7. Using JavaScript for SEO-sensitive moves. Server-side or meta refresh redirects are safer for anything you want indexed cleanly. JavaScript should be a last resort.
  8. 301'ing during a rollback plan. If there's any chance you'll undo the move, don't 301. Browser caches make 301s effectively irreversible for weeks. Use 302 while you're validating, then upgrade to 301 once the change is confirmed final.

Most of these are one-line fixes once you know to look for them. The hardest part is auditing existing redirects on a site that's been alive for years, because chains and loops accumulate silently as different teams add their own rules.

Redirect Types in URL Shorteners

URL shorteners are a specialized case of HTTP redirects: their entire product is the redirect. The choice of code affects how the destination is cached, whether you can change it later without users hitting stale cached URLs, and how search engines treat the short URL versus the destination.

Most modern shorteners use 301 by default. It's the cleanest signal for search engines, browsers cache it for near-instant repeat clicks, and for static use cases (vanity URLs, printed materials, permanent bio links) it's exactly right. When shorteners offer 302 as an option, it's usually for dynamic scenarios: A/B testing between destinations, routing traffic by country or device, or keeping the option to swap a destination after the short link is already in circulation.

At U2L AI, links default to 301 (permanent), which makes them cache-friendly and gives the strongest SEO signal for static use cases. You can flip individual links to 302 (temporary) when you need the flexibility to update destinations without fighting browser caches. Every redirect runs through a global edge network with 330+ locations so the round trip happens close to wherever the click originated, which is one reason we're one of the fastest URL shorteners available. For the full feature breakdown, the features page has the current details.

If you're building your own redirect layer and want the deeper context on how each type intersects with SEO, our piece on whether URL shorteners hurt SEO walks through what Google's engineers actually said and where the folklore comes from. For the permanent-versus-temporary decision specifically, the 301 vs 302 explainer has the full breakdown.

Frequently Asked Questions

What are the main types of URL redirects?

The main types are five HTTP status codes and two client-side techniques. Permanent HTTP redirects: 301 and 308. Temporary HTTP redirects: 302, 303, and 307. Client-side redirects: HTML meta refresh and JavaScript window.location. Server-side HTTP redirects are preferred for both speed and SEO.

What is the difference between 301 and 308 redirects?

Both are permanent redirects. The difference is that 308 strictly preserves the HTTP request method (a POST stays a POST), while 301 historically allowed clients to downgrade POST to GET. Google treats them identically for indexing. Use 308 for APIs where method preservation matters and 301 for regular HTML pages.

What is the difference between 302 and 307 redirects?

Both are temporary redirects that keep the original URL indexed. 307 strictly preserves the request method and body; 302 does not. For HTML pages the two are interchangeable. For API endpoints where a POST or PUT must stay a POST or PUT, use 307.

When should I use a 303 redirect?

Use 303 after processing a form POST to prevent duplicate submissions. This is the Post/Redirect/Get pattern: the browser follows the 303 with a GET request to the confirmation page, and refreshing that page won't resubmit the original form. 303 explicitly forces GET on the follow-up request.

Are meta refresh redirects bad for SEO?

They aren't as bad as their reputation suggests. Google treats a 0-second meta refresh similar to a 301, and a delayed meta refresh similar to a 302. That said, they're slower for users, weaker for accessibility, and can fail on slow connections. Prefer HTTP redirects whenever you can control the response headers.

Do JavaScript redirects hurt SEO?

JavaScript redirects work in Google, but they're the weakest option. Googlebot has to render the page and execute the script, and rendering can fail. If you can use a server-side redirect or a meta refresh, do that first. Reserve JavaScript redirects for cases that require client-side logic like device detection or logged-in state routing.

What redirect type do URL shorteners use?

Most modern URL shorteners default to 301 (permanent) because it's cache-friendly and gives the strongest SEO signal. Some offer 302 (temporary) as an option for dynamic links where you want to change the destination later without browser caching issues. The choice is operational, not SEO-driven, since both codes pass full link equity.

Can I use multiple redirect types in a chain?

Technically yes, but you shouldn't. Redirect chains (any hop-through-hop pattern) slow down browsers, waste crawl budget, and increase the chance of timeouts. Point each source URL directly at its final destination. If you inherited a chain, flatten it in one pass rather than adding another hop.

Pick the Right Code, Skip the Rest

Once you know what each redirect actually does, the choice for any given situation stops being mysterious. 301 for permanent HTML moves. 308 for permanent API moves. 302 for temporary HTML. 307 for temporary APIs. 303 after a POST. Meta refresh only when you cannot touch headers. JavaScript only when the redirect has to be conditional client-side. That covers essentially every situation you'll run into.

If your redirects live inside a URL shortener rather than your own infrastructure, the choice of shortener matters more than the redirect code itself. Pick one with a fast edge network, safety checks, no default chains, and the ability to switch between 301 and 302 when the use case calls for it. Create a free U2L AI account and your links default to 301, run on a global edge network, and give you the operational knobs (analytics, custom domains, dynamic destinations) without a paywall on the basics. For a broader read on adjacent topics, our complete guide to link tracking covers how redirects fit into analytics, and our walkthrough on shortening a URL gets you from long URL to branded short link in under a minute.

Ready to try U2L AI?

Free forever plan. No credit card required.