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

  1. Take a full database backup. Search-replace can’t be undone. With WP-CLI: wp db export backup.sql.
  2. Test on staging if the site matters.
  3. Be specific. Replace https://old-site.com rather than old-site, so you don’t change unrelated text.
  4. 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:

FlagWhat it does
--dry-runReports what would change, changes nothing
--report-changed-onlyLists only the tables and columns with replacements
--skip-columns=guidLeaves the guid column alone
--all-tables-with-prefixAlso covers tables with your prefix that plugins created
--preciseRuns every replacement through PHP instead of SQL: slower, more thorough
--networkCovers all sites of a multisite
--export=file.sqlWrites 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

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.

Developer tools inside WordPress

Developer tools inside WordPress

DevKit: error logs, salts, plugin manager, maintenance mode and more, without FTP or cPanel.

Related guides

Browse all WordPress tutorials.