Build nginx redirects without guessing at syntax. Force HTTPS, pick www or non-www, move single
pages or whole folders, write regex redirects with captures, point an old domain at a new one,
and turn a pasted list of hundreds of URLs into a single map block. The generator
picks the right construct for each job: location = for exact pages,
location ^~ with rewrite for folders, and return with
$request_uri for host-level redirects. It flags loops, redirect chains, duplicate
locations, and query strings that a location block can never match.
Everything is generated in your browser, and nothing you type is sent anywhere. On Apache, the
.htaccess generator builds the equivalent
RewriteRule rules. After you reload nginx, run each old URL through the
redirect checker to confirm the status code and final
destination. Test regex patterns against real paths first in the
regex tester.
Frequently asked questions
Should I use return or rewrite for nginx redirects?
Use return whenever you can. "return 301 /new;" ends the request immediately, needs no regular expression, and accepts any status code, including 307 and 308. Its one catch is that it appends nothing, so to keep the query string you add $is_args$args yourself, which this generator does. rewrite is for pattern-based moves where you need captures like $1. With the permanent (301) or redirect (302) flag it sends a redirect and carries the original query string over automatically. Put a trailing "?" in the replacement to drop it. rewrite cannot send 307 or 308, so for those codes the generator uses return with a regex capture.
Why does the HTTPS redirect use $request_uri instead of $uri?
$request_uri is the original request target exactly as the browser sent it: the path plus the query string, still percent-encoded. Appending it to https://$host gives a lossless redirect, so /search?q=a%20b arrives intact. $uri is the path after nginx has decoded and normalized it, with no query string. It is what location blocks match against, but building a redirect from it would drop ?q=… and could produce unencoded characters in the Location header. The rule of thumb is to use $request_uri when you forward a whole URL to another host, and $uri, or regex captures, when you are matching or rewriting paths.
In what order does nginx evaluate these redirects?
Directives at the server level (the bulk-map "if", regex rewrites, and the trailing-slash rule) run first, top to bottom, before nginx picks a location. Then locations are chosen. An exact "location = /path" match wins immediately. Otherwise nginx finds the longest matching prefix, and if that prefix is marked ^~ (which the folder redirects use), regex locations are skipped. Without ^~, nginx checks regex locations in the order they appear, and the first match beats the prefix. So a folder redirect written as "location ^~ /old/" still works even if you have a "location ~ \.php$" further down. Separate server blocks for http, www, and old domains are chosen by port and Host header before any of this happens.
Where does the map block go, and why can’t it go inside server?
nginx only allows map in the http {} context, so pasting it inside server {} makes nginx -t fail with: "map" directive is not allowed here. Put it in nginx.conf inside the http block, or in a file that the http block includes (most distributions include /etc/nginx/conf.d/*.conf there). The "if ($redirect_target) { return 301 $redirect_target; }" part goes inside your server block. Map keys are matched case-insensitively, and a duplicate key is a fatal error, so the generator flags keys that differ only by case. With thousands of long URLs you may also need map_hash_bucket_size or map_hash_max_size, and the output adds a comment when that's likely.
Which status code should I pick: 301, 302, 307, or 308?
For a permanent move, like a new URL structure, HTTPS, or a www change, use 301 or 308. Both tell search engines to move ranking signals to the new URL. For something temporary, like maintenance or an A/B test, use 302 or 307, because search engines keep the old URL indexed. The difference inside each pair is the request method. With 301 and 302, browsers may turn a POST into a GET when they follow the redirect. 307 and 308 require the same method and body to be sent again, which matters for form posts and API endpoints. For ordinary page redirects, 301 is the most widely supported choice.
Why doesn’t my redirect for /page?id=5 work in a location block?
location blocks never see the query string. They match the decoded path only, so "location = /page?id=5" can never match. When old URLs differ only by their query string, use the bulk map set to match $request_uri. Its keys include the query, so /page?id=5 and /page?id=6 can go to different places. Keep in mind that $request_uri matching is exact. /page?id=5&utm_source=x is a different key and falls through. Also, nothing after "#" is ever sent to the server, so fragments cannot be redirected by nginx at all. Handle those with JavaScript on the page.