# HTTP 301 Moved Permanently — Status Code Meaning & Examples

> The resource has a new permanent URL; clients and search engines should use the Location instead.

301 says 'this moved for good — update your links'. Browsers follow the `Location` header and cache the redirect aggressively, often indefinitely, and search engines pass the old URL's ranking signals to the new one.

That permanence is the point, and also the trap: a mistaken 301 can stay stuck in visitors' browsers long after you remove it from the server.

- Class: 3xx Redirection
- Retry: Not applicable
- Cacheable by default: yes
- Defined in: [RFC 9110 §15.4.2 — 301 Moved Permanently](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.4.2)

## Example response

```http
HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/new-path
```

## When you'll see it

- Domain or URL structure changes: http → https, non-www → www, `/blog/post` → `/posts/post`.
- Normalising trailing slashes or letter case.
- Merging duplicate pages into one.

## How to use it well

1. Redirect each old URL to its closest new equivalent, not everything to the homepage — Google treats mass homepage redirects as soft 404s.
2. Avoid chains (A → B → C); point every old URL straight at the final destination.
3. Use 308 if the request might be a POST: clients may turn a redirected POST into a GET after a 301.
4. Test with `curl -I` — browser caches make 301 mistakes hard to see.

## Send a 301 from your server

### Express

```
res.redirect(301, "https://www.example.com/new-path");
```

### Next.js route handler

```
return NextResponse.redirect(new URL("https://www.example.com/new-path", request.url), 301);
```

### Flask

```
return redirect("https://www.example.com/new-path", code=301)
```

### Go net/http

```
http.Redirect(w, r, "https://www.example.com/new-path", http.StatusMovedPermanently)
```

### nginx

```
return 301 https://www.example.com/new-path;
```

## FAQ

### 301 vs 302 — which should I use?

301 for permanent moves you want search engines to index at the new URL. 302 for temporary detours — maintenance, A/B tests — where the original URL should keep its place in search results.

### 301 vs 308?

Both are permanent. 308 forbids changing the method, so a POST stays a POST; 301 lets clients switch to GET, which browsers do. For page redirects 301 is fine; for APIs prefer 308.

### How do I undo a 301 that browsers cached?

You can't clear visitors' caches. Redirect the new URL back, or serve content at the old one, and the stale redirects will fade as caches expire. Next time, test with a 302 and switch to 301 once you're sure.

## Related status codes

- [302 Found](https://www.devkult.com/http/302.md)
- [308 Permanent Redirect](https://www.devkult.com/http/308.md)
- [307 Temporary Redirect](https://www.devkult.com/http/307.md)
- [410 Gone](https://www.devkult.com/http/410.md)

Open the interactive page: https://www.devkult.com/http/301