How to Search and Replace in the WordPress Database Safely
To change URLs in a WordPress database safely, use a tool that understands serialized data: run wp search-replace with --dry-run first, then for real. A plain SQL REPLACE() corrupts the string lengths stored inside serialized options and post meta.
Moving a site to a new domain, switching from http:// to https://, or renaming something that appears in hundreds of posts: all of these need a search and replace across the database. Done wrong, it breaks widgets, settings and page-builder layouts. Done right, it takes a minute.
Why a plain SQL replace breaks things
WordPress and many plugins store settings as serialized PHP data, which records the length of every string:
s:19:"http://old-site.com";
If you replace http://old-site.com with https://new-site.com directly in SQL, the text is 20 characters long but the data still says s:19. PHP can no longer read it, and the setting silently resets. Page builders and widgets are common victims. A proper search-replace tool unserializes, replaces and re-serializes the data so the lengths stay correct.
Search and replace in WordPress is not a text operation on a database dump. A serialized array records the length of every string it contains, and a replacement that changes that length breaks the array when it is read.
Before you start
- Take a full database backup. Search-replace can’t be undone. With WP-CLI:
wp db export backup.sql. - Test on staging if the site matters.
- Be specific. Replace
https://old-site.comrather thanold-site, so you don’t change unrelated text. - Do a dry run first and look at how many replacements it would make.
Option 1: WP-CLI (the most reliable)
If you have SSH access, WP-CLI handles serialized data correctly:
# See what would change, without changing anything
wp search-replace 'https://old-site.com' 'https://new-site.com' --dry-run
# Run it, skipping the GUID column
wp search-replace 'https://old-site.com' 'https://new-site.com' --skip-columns=guid
# Clear caches afterwards
wp cache flush
Skip the guid column: WordPress uses it as a permanent ID for feeds, and its documentation says to “never, ever, change the contents of the GUID column”.
Flags worth knowing:
| Flag | What it does |
|---|---|
--dry-run | Reports what would change, changes nothing |
--report-changed-only | Lists only the tables and columns with replacements |
--skip-columns=guid | Leaves the guid column alone |
--all-tables-with-prefix | Also covers tables with your prefix that plugins created |
--precise | Runs every replacement through PHP instead of SQL: slower, more thorough |
--network | Covers all sites of a multisite |
--export=file.sql | Writes the changed data to a file and leaves the database untouched |
--export is the safest way to prepare a move: the live database stays as it is, and you import the file on the new server.
When plain SQL is safe: only siteurl and home
Two values are plain text and safe to change directly: the siteurl and home rows in wp_options. Changing them is how you get a moved site to load at all:
wp option update home 'https://new-site.com'
wp option update siteurl 'https://new-site.com'
Everything else (content, widgets, builder data) goes through a search-replace tool.
Option 2: a plugin in wp-admin
Without SSH, use a search-replace plugin that handles serialized data and offers a dry run, then check the result. Some page builders keep their own caches or encoded data; after replacing, regenerate their CSS or caches from the builder’s settings if they offer that.
After the replace: verify and roll back
- Log in again if you changed the site URL (cookies belong to the old domain).
- Clear every cache: page cache, object cache, CDN.
- Check pages built with page builders, menus, widgets and forms.
- Look for mixed-content warnings in the browser console if you switched to https.
- Confirm the URL:
wp option get siteurl.
If something is wrong, restore the backup you took (wp db import backup.sql) and start again with a narrower search string.
Search and replace from wp-admin with DevKit
DevKit, the developer toolbox we build at DPlugins, includes a Search & Replace screen inside wp-admin. It handles serialized data and has a dry run that shows the changes per table before anything is written. Its documentation notes it isn’t yet fully compatible with page builders, so for sites built with a builder, prefer WP-CLI for now. DevKit’s other tools help around a migration: regenerating salts, reading the error log without FTP, and switching on maintenance mode while you work.
FAQ
Why does search and replace break my WordPress site?
Because serialized data stores string lengths. A plain SQL replace changes the text but not the stored length, so PHP can’t read the value and the setting resets. Restore your backup and use a serialization-aware tool.
Should I replace the guid column?
No. GUIDs identify posts for feed readers and are not used as links.
Can I do a dry run?
Yes. With WP-CLI add --dry-run and check the count per table. In a plugin, only trust a preview the plugin documents.
Sources
- wp search-replace, WP-CLI command reference (read 2 October 2026)
- Migrating WordPress, WordPress documentation: the GUID note (read 2 October 2026)
- serialize(), PHP Manual (read 2 October 2026)
- Search/Replace, DevKit documentation (read 2 October 2026)
Tested with WordPress 7.1.2 and WP-CLI 2.12.0: --dry-run, --report-changed-only, --skip-columns, --all-tables-with-prefix, --precise and --export.
Related guides
- How to Install and Update Multiple WordPress Plugins at Once: Your plugin toolkit on a new site in one step.
- How to Update Private WordPress Plugins from GitHub: One-click updates from GitHub for your own plugins.
- Nulled WordPress Plugins: What You Really Get (and a Safer Way to Save Money): Backdoors, no updates, and a safer way to save money.
- How to Enable and Read the WordPress Error Log: Turn on logging and read errors, without FTP.
Browse all WordPress tutorials.
