What does it do, and who is it for?
Migrations and URL restructures need a correct redirect for every old address. The tool turns source path and target URL pairs into RewriteRule lines that Apache and LiteSpeed servers understand. It catches conflicting targets, self-redirects, loops and avoidable chains before generating anything. It is built for WordPress developers changing permalinks, site owners on shared hosting such as Hostinger, and SEOs preparing migration maps.
How to use it
- For one redirect, stay in “Single” mode, enter a source path such as
/old-pageand an absolute target URL, then choose 301 or 302 and the query behaviour. - For many addresses switch to “Bulk (CSV)” and paste the table or pick a UTF-8 CSV file of up to 1 MiB.
- Enter your site host. Loop detection uses it to tell which targets live on your site.
- Optionally enable the HTTPS and host block and pick the server environment.
- Press “Generate rules”, read the errors and warnings, then copy or download the output.
Generation rules: exact paths only
The source field is not a regex. The path is percent-decoded and normalised to NFC, then every regex metacharacter is escaped. In a root .htaccess Apache matches the path without its leading /, so that character is removed and the pattern is anchored with ^…$. As a result /old never catches /old-extra, and the dot in /a.b does not mean “any character”.
- Sources with a query, a fragment,
%2F,%5C, control characters or ambiguous double encoding such as%252Fare rejected. /ışıkand/%C4%B1%C5%9F%C4%B1kcount as the same source and produce the same rule.- Targets must be absolute HTTP/HTTPS without a fragment. They are written already encoded, and the
NEflag stops Apache from encoding them twice. - Chains produce a warning, but targets are never rewritten automatically.
301 versus 302
A 301 announces a permanent move: search engines adopt the new address over time and browsers may cache it for long. A 302 is temporary, for cases where the old address returns, such as a campaign or maintenance page. Using 302 for a permanent move can delay adoption of the new URL.
Bulk CSV and a worked example
Columns are source,target,status,query, with an optional header row. An empty status means 301 and an empty query means keep. Quote fields that contain commas, or switch to the semicolon delimiter for spreadsheet exports. Up to 500 rows are processed; beyond that you get an error rather than silent truncation.
source,target,status,query
/eski-hizmet,https://www.example.com/hizmetler/,301,keep
/ışık-ürünleri,https://www.example.com/aydinlatma/,301,dropWith the site host www.example.com and the HTTPS block enabled, this table produces the block below. The second rule carries QSD, so /ışık-ürünleri?renk=beyaz lands on the new page without its query. Path rules come before the host block, so http://example.com/eski-hizmet reaches the final URL in a single hop.
# BEGIN Redirects
# Place this block above "# BEGIN WordPress" in the site root .htaccess.
<IfModule mod_rewrite.c>
RewriteEngine On
# Exact-path redirects
RewriteRule ^eski-hizmet$ https://www.example.com/hizmetler/ [R=301,L,NE]
RewriteRule ^ışık-ürünleri$ https://www.example.com/aydinlatma/ [R=301,L,NE,QSD]
# HTTPS + canonical host (TLS terminates on this server)
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
</IfModule>
# END RedirectsQuery string behaviour
Rules follow the Apache RewriteRule flags:
| Choice | Target has a query | Result |
|---|---|---|
| Keep | No | The original query is passed through unchanged; no flag is needed. |
| Keep | Yes | The target's query wins and the original is dropped; nothing is merged with QSA. |
| Drop | Either | The QSD flag discards the original query; a target query stays. |
The WordPress block and rule order
WordPress rewrites the section between # BEGIN WordPress and # END WordPress whenever permalinks are saved, so paste the block above it; anything inside can be lost. The WordPress block also routes every request to index.php, so redirects must run first. With a redirect plugin too, never define one address in both places.
Hostinger, LiteSpeed and Cloudflare
“Direct HTTPS” mode relies on %{HTTPS} and is meant for setups where TLS terminates on this server. Behind a proxy it can always look off, causing an endless loop. Proxy mode trusts the X-Forwarded-Proto header, so use it only when a trusted proxy sets it and the origin is not directly reachable. The target host is always the host you typed; the unvalidated %{HTTP_HOST} is never used as a target.
With Cloudflare's Flexible SSL mode, Cloudflare talks to your server over HTTP, the server's HTTPS redirect sends visitors back to HTTPS, and the loop begins. Use Full (strict) with a valid certificate. Hostinger's LiteSpeed servers read .htaccess, but behaviour can vary by version, so test in a staging directory first.
Rolling back and common mistakes
- Back up the current
.htaccessbefore editing. If something breaks, restore the backup or delete the block between# BEGIN Redirectsand# END Redirects. - Browsers cache 301 responses; test in a private window or with
curl -I. - A 500 error usually means a typo or a disabled
mod_rewrite; check the server error log. - The output is built in your browser; the tool never connects to or verifies your live server.
Frequently asked questions
Where do I paste the generated code?
Into the .htaccess file in your site root, above the # BEGIN WordPress line. An .htaccess in a subdirectory matches paths differently; this output is written for the root.
Can I write regex patterns for bulk matches?
This version generates exact path matches only. Every special character in the source is escaped, so typing * or (.*) means those literal characters, not a wildcard.
Are UTM parameters on the old URL preserved?
With “Keep” and no query on the target, the original query string passes through unchanged. A target with its own query uses that query instead.
Why do I get a loop error?
If A points to B and B back to A, or an address points to itself, the rules redirect forever. For targets on another domain, fill in your site host so they count as external.
How do I test the redirects?
After uploading, run curl -I https://yourdomain.com/old and check the status code and Location header, including for a URL with a query.