> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# URL Redirect Rewrite

> Explains how to use Nginx redirects and rewrites, differences, examples, variables, regex captures, status codes, and best practices for internal mapping and SEO-friendly redirects

In this lesson we cover how to use Nginx to redirect and rewrite URLs — two related but distinct techniques that let you move, consolidate, or hide resources without breaking links or losing SEO value.

Short analogies:

* Redirect = mail forwarding (postal service tells the client to fetch mail at the new address).
* Rewrite = mail slip that silently changes the delivery address (the recipient remains unaware the envelope was modified).

When a request arrives for a server name Nginx matches, you can either instruct the client to request a different address (redirect) or internally map the request to a different resource (rewrite).

![A flow diagram showing how an NGINX proxy handles a request for honda.cars.com, passes it through decision logic, and redirects to various subdomains (cars.com, honda.cars.com, toyota.cars.com). The diagram then shows another NGINX/decision step mapping those to new domains like honda.com, cars.honda.com, and bikes.honda.com with the response returned to the requester.](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Intermediate-Config/URL-Redirect-Rewrite/nginx-proxy-honda-cars-redirect-mapping.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=574781058eeca048078b10cfd20000ff)

## Redirects with the return directive (recommended for simple redirects)

Use the `return` directive for simple, predictable redirects (it’s fast and clear). Example: redirect all requests for `honda.cars.com` to `cars.honda.com`, preserving path and query string.

```nginx theme={null}
server {
    listen 80;
    server_name honda.cars.com;

    # Redirect all requests to the new domain while preserving the path and query string
    return 301 https://cars.honda.com$request_uri;
}
```

Use `301` for permanent moves (good for SEO). Use `302` for temporary moves.

Example — redirect HTTP to HTTPS on the same host while preserving the requested URI:

```nginx theme={null}
server {
    listen 80;
    server_name honda.cars.com;

    # Redirect to HTTPS on the same host, preserving the full request URI (path + query)
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name honda.cars.com;

    ssl_certificate /etc/ssl/certs/honda.cars.com.pem;
    ssl_certificate_key /etc/ssl/certs/honda.cars.com-key.pem;

    root /var/www/honda.cars.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
```

When redirecting to HTTPS you must configure valid TLS certificates and a 443 server block. Also be careful with `301` (permanent): user agents and search engines may cache permanent redirects.

### Nginx built-in variables used in redirects

* `$host` — the Host header from the request (or the server name matched).
* `$request_uri` — the original request URI including path and query string, e.g. `/2024/civic-type-r?color=red`.

Example flow:

```text theme={null}
Request:
  Host: honda.cars.com
  GET /2024/civic-type-r?color=red HTTP/1.1

$request_uri
  -> /2024/civic-type-r?color=red

Return redirect:
  https://cars.honda.com$request_uri
  -> https://cars.honda.com/2024/civic-type-r?color=red
```

Prefer `return` for simple domain or scheme redirects because it is more efficient and clearer than using `rewrite` for the same purpose. Use `rewrite` when you need pattern-based URL transformations or internal mapping.

### Redirect a single page with a location block

If only a single path should be redirected, place the `return` inside a `location`:

```nginx theme={null}
server {
    listen 80;
    server_name honda.cars.com;

    root /var/www/example.com/html;
    index index.html;

    location /civic-type-r {
        return 301 https://cars.honda.com$request_uri;
    }
}
```

## Inspecting redirects in the browser

Open DevTools → Network tab to view request/response details: method, status, headers, and where the redirect points.

![A screenshot of a browser's Developer Tools Network tab showing a table of HTTP requests (GET/POST), domains, file names, statuses and sizes. Several requests to Google and related domains are listed, with some entries marked "Blocked By uBlock."](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Intermediate-Config/URL-Redirect-Rewrite/devtools-network-requests-ublock-blocked.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=bdd745ee1a8b7f7a0427e49b4b63fe0d)

## Common HTTP status codes (high level)

Use the table below as a quick reference for status codes you’ll see while adding redirects and rewrites.

| Status | Meaning | When to use |
| - | - | - |
| `200` | OK — successful request | Normal page response |
| `301` | Moved Permanently | Permanent redirect; SEO-friendly |
| `302` | Found / Temporarily Moved | Temporary redirect |
| `400` | Bad Request | Client error — malformed request |
| `401` | Unauthorized | Authentication required |
| `403` | Forbidden | Authenticated but not permitted |
| `404` | Not Found | Resource not found |
| `500` | Internal Server Error | Server-side failure |
| `502` | Bad Gateway | Invalid response from upstream |
| `503` | Service Unavailable | Server cannot handle request now |

![An infographic titled "Status Codes" listing common HTTP response codes (200, 301, 302, 400, 401, 403, 404, 500, 502, 503) with short plain-language explanations of each. It explains meanings like "200 - Everything is good," redirects (301/302), client errors (400–404), and server errors (500–503).](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Intermediate-Config/URL-Redirect-Rewrite/http-status-codes-infographic.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=b747aa13034ec72d5f41f6cec22c2e03)

## Rewrite rules (internal mapping or pattern-based redirects)

A rewrite modifies the request URI Nginx uses internally or produces a redirect based on a pattern. Use rewrites when you need to map legacy paths, normalize URLs, or capture parts of a path and reuse them.

Analogy: the post office updates the delivery address on the envelope (internal change) or sends the mailer a forward notice (redirect).

![A stylized computer screen shows an address update form listing "Old Address: 111 Main Street Apartment" and "New Address: 555 Meadows Drive" with an "Update" button.](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Intermediate-Config/URL-Redirect-Rewrite/address-update-form-old-new.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=5e97e022de6bb0b54c69b07bb7201b29)

### Simple rewrite example (pattern → new path)

This example issues a permanent redirect from a legacy long path to a cleaner path:

```nginx theme={null}
server {
    listen 80;
    server_name honda.cars.com;

    root /var/www/example.com/html;
    index index.html;

    # Redirect the legacy long URL to a shorter path (permanent redirect)
    rewrite ^/sports-car-civic-type-r$ /type-r permanent;
}
```

Note: `permanent` emits a `301`. If you want the behavior to be internal (no change in browser URL), avoid `permanent` and use `try_files` or `alias`.

### Serve images from a new path using rewrite or internal mapping

Example project tree (images in `pics/`):

```bash theme={null}
$ tree
.
|-- 50x.html
|-- index.html
`-- pics
    |-- accord.jpg
    |-- civic.jpg
    `-- type-r.jpg
```

Options:

* Rename the folder on disk to `images/` and update links.
* Keep files in `pics/` and map `/images/*` requests to `pics/` internally.

Example: emit a redirect from `/pics/*` to `/images/*`:

```nginx theme={null}
server {
    listen 80;
    server_name honda.cars.com;

    root /var/www/example.com/html;
    index index.html;

    location /pics {
        # Capture everything after /pics/ and rewrite to /images/<captured>
        rewrite ^/pics/(.*)$ /images/$1 permanent;
    }
}
```

If you need an internal mapping without changing the browser URL, use `try_files` or `alias` inside `location`:

```nginx theme={null}
location /images/ {
    alias /var/www/example.com/html/pics/;
}
```

### Why use rewrites?

* Preserve bookmarks and inbound links after reorganizing content.
* Provide clean, SEO-friendly URLs.
* Map legacy URLs to current resources without duplicating files.

## Regular expressions (regex) primer for rewrite rules

Rewrite directives commonly use regular expressions to match and capture parts of the URI.

![A slide titled "Regular Expression 101" with the definition "Regex is a sequence of characters that forms a search pattern." Below it are three rounded cards with colorful icons labeled "Search text," "Match text," and "Manipulate text."](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Intermediate-Config/URL-Redirect-Rewrite/regex-101-search-match-manipulate.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=ea34b4c6c58373407f715d9b6904683e)

Common regex metacharacters:

* `^` — start of the string
* `$` — end of the string
* `.` — any single character
* `*` — zero or more of the preceding token
* `+` — one or more of the preceding token
* `?` — zero or one of the preceding token
* `( … )` — capture group
* `[...]` — character class (e.g., `[a-zA-Z0-9_]`)
* `|` — alternation (OR)
* `\d` — digit, `\w` — word character, `\s` — whitespace

Example regex that matches lowercase letters, digits, or hyphens only:

```regex theme={null}
/^[a-z0-9-]+$/
```

Matching examples:

* `^/[a-z-]+$` matches `/hello-world` but not `/HELLO-WORLD`.
* `^/[a-zA-Z-]+$` matches `/hello-world` and `/HELLO-WORLD`.
* `^/[a-zA-Z0-9_\/-]+$` matches `/hello123` and `/hello_W0R1D`.

For interactive regex testing and explanation, try Regex101: [https://regex101.com](https://regex101.com).

### How captures work in rewrite rules

You can capture parts of the matched URI and reuse them with `$1`, `$2`, etc.

```nginx theme={null}
rewrite ^/old_page/(.*)$ /new_page/$1 permanent;
```

* `(.*)` captures everything after `/old_page/`.
* `$1` inserts that captured text into the replacement.
* `/old_page/section1` → `/new_page/section1`.

## Useful links and references

* Nginx documentation: [https://nginx.org/en/docs/](https://nginx.org/en/docs/)
* Regex testing: [https://regex101.com](https://regex101.com)

## Wrapping up

We covered:

* Using `return` to issue redirects (domain changes, HTTP → HTTPS).
* Important Nginx variables (`$host`, `$request_uri`).
* How to inspect redirects in browser DevTools.
* Common HTTP status codes and their meanings.
* Using `rewrite` for pattern-based mapping and capturing with regex.
* When to use `try_files`, `alias`, or `return` depending on whether you want internal rewrites or client-visible redirects.

Now let’s move to a demo to see these rules in action.

> **[Watch Video](https://learn.kodekloud.com/user/courses/nginx-for-beginners/module/c78ff9cb-c15d-4f85-92fc-abee5ed98b20/lesson/55d731cf-41af-43c3-81f3-469afda88435)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.