Changing many URLs at once, for example to clean up old slugs, move a blog into a new folder or switch platforms, is safe only if every old address answers with a permanent redirect to the closest new page. This guide walks through the whole job in seven steps: list the old URLs, map each one, generate the rules, remove chains and loops, update your own links, test, and monitor. The advice on redirects follows Google Search Central's documentation, which is linked in the sources. Every rule shown below is real output from our 301 redirect generator.
When a bulk URL change is worth it
Google treats changed URL paths as a site move, even when the domain stays the same. Search traffic usually fluctuates while Google recrawls the site: for a medium-sized site, Google says it can take a few weeks or more before the new URLs replace the old ones in results. So change URLs in bulk when there is a lasting gain:
- The old URLs are broken or misleading. Examples are
index.php?p=123addresses, dates that make evergreen posts look stale, or slugs that no longer match the page. - The structure is changing anyway. A new CMS, a merged blog or a new folder layout will change URLs no matter what, so fix the slugs in the same move.
- You are consolidating content. Several thin pages become one stronger page.
Do not change URLs only to make slugs a few characters shorter. Our URL slug length guide explains why the length of a published slug is rarely worth a migration.
301, 308, 302 or something else?
| Method | Type | How Google treats it | When to use it |
|---|---|---|---|
| HTTP 301 / 308 | Permanent, server-side | Strong signal that the target should be canonical | URL changes and migrations (the default for this guide) |
| HTTP 302 / 303 / 307 | Temporary, server-side | Weak signal; the old URL tends to stay in results | Short-term moves, A/B tests, maintenance |
meta refresh with 0 seconds | Permanent | Treated like a permanent redirect | Only when you cannot configure the server |
meta refresh with a delay | Temporary | Treated like a temporary redirect | Rarely useful |
JavaScript location | Depends on rendering | Google may miss it if rendering fails | Last resort, when nothing above is possible |
Google recommends server-side redirects whenever possible. A 301 and a 308 are both permanent; 301 is what most tools, including ours, write by default. Google also states that 301 and other permanent redirects don't cause a loss in PageRank, so a correct redirect passes the old page's signals to the new one.
Step 1: list every old URL
You cannot redirect what you do not know about. Combine several sources, because each one misses something:
- Your XML sitemap and CMS export. These cover the pages you know you published.
- Server logs and analytics. These show the URLs that people and crawlers actually request, including old variants.
- Search Console. The Pages and Links reports show indexed URLs and the pages that other sites link to.
- Images, PDFs and videos. Files with changed paths need redirects too.
Put everything in one spreadsheet column and remove exact duplicates. Keep the original capitalization, because URL paths are case-sensitive: /Blog/Summer_Sale_2024 and /blog/summer_sale_2024 are different URLs.
Step 2: map each old URL to the closest new page
Every old URL needs exactly one destination, and that destination should match the old content as closely as possible.
- Redirect to the equivalent page. A post goes to the same post at its new address, a category to the new category.
- Do not send everything to the home page. Google warns that redirecting many old URLs to one irrelevant page, such as the home page, can confuse users and might be treated as a soft 404.
- Let removed content go. If a page is deleted with no replacement, return 404 or 410 instead of redirecting it somewhere unrelated.
- Merged pages are the exception. If several old pages were combined into one new page, redirecting all of them to it is correct.
When the new URLs do not exist yet, map each old URL to the new page title and let a tool create the slug. Here is a real input for the redirect generator in Old → new title (slug) mode, with the path prefix /blog/ and the site URL https://example.com:
/blog/2019/05/10-tips-for-better-slugs -> 10 Tips for Better URL Slugs
/index.php?p=123 -> How to Bake Sourdough Bread at Home
/Blog/Summer_Sale_2024 -> Summer Sale, Up to 50% OffThe generator turns the titles into these targets with its default settings:
| Old URL | New URL |
|---|---|
/blog/2019/05/10-tips-for-better-slugs | https://example.com/blog/10-tips-for-better-url-slugs |
/index.php?p=123 | https://example.com/blog/how-to-bake-sourdough-bread-at-home |
/Blog/Summer_Sale_2024 | https://example.com/blog/summer-sale-up-to-50-percent-off |
Have hundreds of rows in a CSV? The bulk CSV slug generator creates the slugs and the redirect column in one pass.
Step 3: generate the redirect rules
Write the rules in the format your server understands. These are the real outputs for the three redirects above.
Apache (.htaccess):
Redirect 301 /blog/2019/05/10-tips-for-better-slugs https://example.com/blog/10-tips-for-better-url-slugs
Redirect 301 /Blog/Summer_Sale_2024 https://example.com/blog/summer-sale-up-to-50-percent-off
RewriteEngine On
RewriteCond %{QUERY_STRING} ^p=123$
RewriteRule ^index\.php$ https://example.com/blog/how-to-bake-sourdough-bread-at-home? [R=301,L]Apache's Redirect matches the start of the path, but only complete path segments, and the match is case-sensitive. Rules are processed in the order they appear and the first match wins, so put specific paths before broader ones. Redirect cannot see the query string, which is why /index.php?p=123 needs RewriteCond and RewriteRule. The trailing ? drops the old query string from the target.
Nginx:
location = /blog/2019/05/10-tips-for-better-slugs { return 301 https://example.com/blog/10-tips-for-better-url-slugs; }
if ($request_uri = "/index.php?p=123") { return 301 https://example.com/blog/how-to-bake-sourdough-bread-at-home; }
location = /Blog/Summer_Sale_2024 { return 301 https://example.com/blog/summer-sale-up-to-50-percent-off; }location = is an exact match, so /Blog/Summer_Sale_2024/extra is not affected. Put these lines inside the right server block.
Cloudflare Bulk Redirects (CSV):
example.com/blog/2019/05/10-tips-for-better-slugs,https://example.com/blog/10-tips-for-better-url-slugs,301
example.com/index.php,https://example.com/blog/how-to-bake-sourdough-bread-at-home,301
example.com/Blog/Summer_Sale_2024,https://example.com/blog/summer-sale-up-to-50-percent-off,301The CSV must not have a header row, and a URL that contains a comma must be wrapped in double quotes. Cloudflare source URLs cannot include a query string, so the second line matches every request to /index.php, whatever its parameters. If you have several ?p= URLs, handle them on your origin server with the Apache or Nginx rules instead.
Step 4: remove redirect chains and loops
A chain is a redirect whose target is redirected again: /old-a → /old-b → /new-c. Googlebot follows up to 10 hops, but Google advises redirecting to the final destination directly, and otherwise keeping chains to ideally no more than 3 and fewer than 5 hops. Chains add latency, and not every browser follows long chains.
Chains appear when an old redirect list meets a new one. Given these four lines:
/old-a -> /old-b
/old-b -> /new-c
/x -> /y
/y -> /xthe generator flags all three problem lines. With Flatten redirect chains turned on, it writes:
Redirect 301 /old-a /new-c
Redirect 301 /old-b /new-c
Redirect 301 /x /y
Redirect 301 /y /xThe first two are now direct redirects. /x → /y → /x is a loop: it can never resolve, so it cannot be flattened. The generator keeps both lines so you can see them and shows a "Redirect loop" warning for lines 3 and 4. Decide which URL is the real page and delete the other rule before you deploy.
Step 5: update your own links and signals
Redirects catch old links from other sites. Everything you control should point to the new URLs directly:
- Internal links in navigation, body text and templates.
- Canonical tags: each new page should have a self-referencing
rel="canonical". - hreflang annotations on multilingual pages, in HTML or in the sitemap.
- XML sitemaps: list the new URLs. Google's site move guide also suggests submitting a sitemap of the old URLs, so you can watch them drop out of the index as the new ones replace them.
- Ads, emails and social profiles that link to old pages.
Search Console's Change of Address tool is only for moves from one domain or subdomain to another. You don't need it when paths change on the same domain.
Step 6: test every redirect
Test the whole list, not a sample. This Bash script reads old_url,expected_url lines and checks that each old URL returns a 301 to the expected address, and that the target returns 200:
#!/usr/bin/env bash
# usage: ./check-redirects.sh redirects.csv (lines: old_url,expected_url; no header)
fail=0
while IFS=, read -r old expected; do
expected=${expected%$'\r'}
read -r code location < <(curl -s -o /dev/null -w '%{http_code} %{redirect_url}' "$old")
final=$(curl -s -o /dev/null -w '%{http_code}' "$expected")
if [[ $code == 301 && $location == "$expected" && $final == 200 ]]; then
echo "OK $old"
else
echo "FAIL $old -> $code $location (target $final)"; fail=1
fi
done < "$1"
exit $failThen inspect a few important URLs with the URL Inspection tool in Search Console to confirm that Google sees the redirect.
Step 7: monitor and keep the redirects
- Keep redirects for at least a year. Google recommends keeping them as long as possible, generally at least 1 year, so that all signals move to the new URLs. Keeping them forever is fine.
- Watch Search Console. Check the Pages report for new 404 and soft 404 errors, and compare the two sitemaps: indexed pages in the old-URL sitemap should fall toward zero while the new-URL sitemap rises.
- Expect some fluctuation. Rankings can move while Google recrawls. A few weeks or more is normal for a medium-sized site, and longer for large ones.
Warning
Common mistakes
- Leaving noindex or a robots.txt block from staging on the new pages, so the redirect targets cannot be indexed.
- Redirecting old pages to the home page or another irrelevant page instead of the closest match.
- Forgetting the sitemap, which keeps listing old URLs that now redirect.
- Ignoring case:
/Blog/and/blog/are different paths on most servers, so redirect the version that was actually published. - Apache prefix surprises:
Redirect 301 /blog /newsalso redirects/blog/any-postto/news/any-post. Order specific rules first. - Placing rules after the CMS block. In WordPress, put your redirects above the
# BEGIN WordPresssection, or the CMS may answer first. - Removing redirects after a few weeks because traffic looks stable.
- Using a 302 by accident. Many plugins and hosting panels default to temporary redirects. Check the status code in the test.
Copyable bulk URL change checklist
[ ] The change has a lasting benefit (not just a few characters shorter)
[ ] Old URLs collected from sitemap, CMS, logs, analytics and Search Console
[ ] Every old URL mapped to the closest new page; deleted pages return 404/410
[ ] No mass redirects to the home page
[ ] Rules generated for the right server (Apache, Nginx or Cloudflare)
[ ] Query-string URLs handled on the origin server
[ ] No chains (each old URL points to its final URL) and no loops
[ ] Internal links, canonical tags, hreflang and sitemap updated
[ ] Every redirect tested: 301 to the expected URL, target returns 200
[ ] No noindex or robots.txt block left on new pages
[ ] Redirects kept for at least 1 year; Search Console monitoredBuild the redirect map with the tools
Use the bulk CSV slug generator to create new slugs from a spreadsheet of titles, then paste the old and new URLs into the 301 redirect generator to get Apache, Nginx or Cloudflare rules with chain and loop checks. For non-English titles, read how to transliterate slugs first, and see the URL slug SEO guide for what makes a good slug. Moving a WordPress site to a new permalink structure? See the WordPress permalink guide.
Sources
- Google Search Central: Redirects and Google Search
- Google Search Central: Site moves with URL changes
- Google Search Central: HTTP status codes and Google's crawlers
- Apache HTTP Server 2.4: mod_alias Redirect directive
- nginx: location directive
- Cloudflare: Bulk Redirects CSV file format
FAQ
Frequently asked questions
Do 301 redirects lose PageRank?
No. Google states that 301 and other permanent redirects don't cause a loss in PageRank. Traffic can still fluctuate for a few weeks while Google recrawls the old and new URLs.
How long should I keep 301 redirects?
Google recommends keeping them as long as possible, generally at least one year. Many sites keep them permanently because a redirect costs almost nothing.
Can I redirect all old URLs to the home page?
Not as a shortcut. Google warns that sending many old URLs to one irrelevant page may be treated as a soft 404. Redirect each URL to its closest match and return 404 or 410 for content that no longer exists.
How many redirects can the generator handle?
The 301 redirect generator accepts up to 5,000 lines at a time. The bulk CSV slug generator has no fixed row limit and previews the first 200 rows. Both run entirely in your browser.
