WordPress Search-Replace Generator
Build a safe wp-cli search-replace command for a domain or URL change, without corrupting PHP-serialized data.
Your details
Command
# Run this over SSH, from your WordPress root, with WP-CLI installed.
wp search-replace \
'http://old-site.com' \
'https://new-site.com' \
wp_posts \
wp_postmeta \
wp_options \
--skip-columns=guid \
--dry-run
# Once the dry run looks right, drop --dry-run to actually run it:
wp search-replace \
'http://old-site.com' \
'https://new-site.com' \
wp_posts \
wp_postmeta \
wp_options \
--skip-columns=guid
wp search-replace safely updates PHP-serialized data (widgets, theme mods, some plugin settings) by re-counting string lengths as it goes. A plain SQL find-and-replace does not, and corrupts any serialized value it touches.
No SSH or WP-CLI access? Use a plugin such as Better Search Replace or WP Migrate instead: they wrap the same serialization-safe logic in the WordPress admin.
Why not a plain SQL find-and-replace
WordPress stores some settings (widgets, theme mods, many plugin options) as PHP-serialized strings, where each piece of text is prefixed with its exact byte length, like s:23:"http://old-site.com/x". A plain SQL REPLACE() changes the text but not that length prefix, so PHP can't unserialize the value anymore and the setting silently breaks. wp-cli's search-replace recalculates those lengths as it rewrites each value, so it's the safe way to change a URL across a whole database.
This tool builds that command for you: pick your old and new URL, choose which tables to touch, and it adds --skip-columns=guid by default, since WordPress treats a post's GUID as a permanent identifier, not a link to update.
Running the command
- 01
Back up your database first
Take a full backup (or a snapshot with your host) before running any search-replace across production data.
- 02
Run the dry run
The generated command includes
--dry-runby default, which shows what would change without touching the database. - 03
Run it for real
The tool also prints the same command without
--dry-run, once the dry run output looks right. - 04
Check the site
Clear any caching plugin and CDN cache, then browse the site to confirm links, images and settings are correct.
Pitfalls
- No SSH or WP-CLI access on your host? Use a plugin such as Better Search Replace or WP Migrate instead: both wrap the same serialization-safe logic in the WordPress admin.
- Run the http-to-https and www/non-www changes as separate passes if you need both, since each is really a different old-to-new pair.
- Multisite installs need
--networkto reach every site's tables; without it, only the current site is touched.
Questions people ask
Is this safe to run on a live site?
It's the same tool developers use for this, but always back up first and run the dry run before the real command. A URL change also often needs a cache clear afterward.
Why skip the GUID column?
A post's GUID is meant to be a permanent identifier, not a working link, so WordPress and most migration guides recommend leaving it untouched even when the domain changes.
What's --precise for?
It switches from a SQL-based search to a PHP-based one, which is slower but catches some multibyte character edge cases the SQL method can miss. Most sites don't need it.
Do I need this for a Shopify store?
No, this is WordPress/WooCommerce-specific. Shopify doesn't store serialized PHP data, so a domain change there is handled through Settings → Domains instead.
Related tools
Last reviewed 30 September 2026.
Sources: WP-CLI: wp search-replace
