#

Maintenance

Subscribe
Maintenance October 29, 2026·10 min read

WP-CLI Search-Replace: Safe URL Changes, Dry Runs, and Verification

Use WP-CLI's serialization-aware search-replace when you've confirmed URLs in your WordPress database need changing. Confirm which installation you're targeting, keep a recoverable SQL backup, and approve the table scope with --dry-run. Then search the database for leftover references and load the pages visitors see.

The basic preview command is wp search-replace OLD NEW --skip-columns=guid --dry-run, with your old and new strings in place of OLD and NEW.

When WP-CLI search-replace is the right tool

WordPress URL replacement

wp search-replace fits when a domain, staging-path, or HTTP-to-HTTPS change leaves old URLs in your database. Absolute links can linger in posts, widget settings, or plugin options. The command edits the database data you select. It can't move site files or change web-server redirect rules.

  • You know the database references: You have the old value, the replacement, database access, and a way to recover.
  • Only WordPress Address or Site Address is wrong: Fix the options or configuration that control the effective WordPress URL.
  • The whole installation is moving: Plan the file transfer, database transfer, destination configuration, and cutover as a full migration.
  • You have no usable CLI access: Use a supported hosting interface or a WordPress plugin.

Confirm the site and the exact strings before changing anything

WordPress installation identity

On a server with several WordPress installations, correct syntax can still target the wrong database. WP-CLI's global --path option names the installation to operate on. Don't rely on the current shell directory.

For a single-site installation, these commands inspect the target without changing anything:

wp --path=/path/to/site core is-installed
wp --path=/path/to/site config get DB_NAME
wp --path=/path/to/site db prefix
wp --path=/path/to/site option get home
wp --path=/path/to/site option get siteurl

config get DB_NAME reads the configured database name from wp-config.php. The prefix shows how WordPress names its tables. It doesn't prove that other applications or installations have no tables in the same database. On multisite, the selected site's --url context also matters.

Find the exact old value in the records you want to change, including http or https, www, the hostname, and any subdirectory. http://example.com, https://example.com, and https://www.example.com are different strings.

Staging URL comparison

One r/Wordpress poster planning a staging-directory test wrote, “I wish to test a manual migration process (from /staging to /test folder before moving to /root folder).” (r/Wordpress staging migration discussion) The path matters: replacing https://example.com/staging with https://example.com/test leaves the hostname alone.

A fragment like example can also appear in unrelated data, so search for the full literal as stored.

Back up the database before the replacement

WordPress SQL backup

A bulk database change needs a recovery point. wp db export, also available as wp db dump, writes the database to SQL using your WordPress database configuration. Unless you restrict the tables, the dump includes every table in the configured database, which matters when another application shares it.

wp --path=/path/to/site db export \
  /secure-backups/before-url-change.sql

The destination directory must already exist and be writable. Store the export outside the publicly served site directory with suitable access controls. Then confirm the file exists, finished successfully, and can be accessed through your recovery procedure.

Don't confuse the SQL dump with a content export. wp db export creates an SQL database dump. wp export creates WordPress eXtended RSS (WXR), an XML file of content records, including posts, comments, terms, and attachment information. WXR omits site options and the actual media files, so it can't serve as a complete database recovery snapshot. The WP-CLI WXR export reference documents that narrower purpose.

SQL export distinction

If you need a complete recovery, copy the WordPress files too: uploads, themes, plugins, and configuration.

Why serialized WordPress data needs a serialization-aware replacement

PHP serialized strings

PHP serialized strings store their byte lengths beside their values. The sample URL https://old.example contains 19 ASCII bytes and can appear as s:19:"https://old.example";. A blanket SQL text replacement that changes the length can invalidate the stored value and damage plugin or widget settings. WP-CLI's search-replace handles serialized data, using PHP processing where necessary alongside SQL processing for other values. The optional --precise flag forces PHP processing for all columns and is slower.

Select which tables and columns the command can change

WordPress table scope

Table selection decides what a URL replacement can change.

SelectionCoversUse it whenWatch for
DefaultRegistered $wpdb tables for the selected siteThe old URLs sit in the usual WordPress dataPlugin tables that aren't registered are left out
Named tablesOnly the tables you listYou know exactly where the old URLs areOther tables holding the old URL stay untouched
--all-tables-with-prefixTables with the configured prefixPlugin tables use your prefixA matching prefix doesn't prove the table belongs to this site
--all-tablesEvery table in the database, regardless of prefixDatabase-wide work is explicitly authorizedUnrelated applications or sites can be affected
--networkRegistered tables across a multisite networkA network-wide change is approvedArbitrary plugin tables aren't included automatically

Pick the smallest scope that covers the data you need to change. --all-tables extends the operation to the whole database, which matters most on shared hosting or a shared database.

Protect GUIDs and know which tables get skipped

During a URL migration, use --skip-columns=guid. A WordPress guid can look like an old permalink, but it works as a persistent identifier, and changing it can disrupt feed identification. The WP-CLI search-replace command reference documents column exclusions and scope options.

WP-CLI skips tables that lack a primary key and never modifies primary-key values. Both rules apply on top of the guid exclusion. If a table you need is missing, check its ownership and schema. A DESCRIBE query shows whether it has a PRI key.

Database column exclusions

Run a dry run and read what would change

WP CLI dry run

A dry run reports the replacements it would make and writes nothing to the database.

wp --path=/path/to/site search-replace \
  'https://old.example' 'https://new.example' \
  --skip-columns=guid --dry-run

The example assumes the single-site target from earlier and the default table scope. If default coverage doesn't suit your site, add the approved table restriction to the preview.

What the preview showsCauseWhat to do
Zero replacementsThe old string isn't there, the scheme or host differs, or you targeted the wrong site or tablesCheck the exact string and confirm --path points at the right site
More matches than expectedA broad string, widespread old links, or too many tablesCheck which tables and columns the matches come from
Expected plugin table absentIt isn't registered, you excluded it, or it has no primary keyCheck who owns the table and whether it has a primary key
Unexpected table presentThe scope covers data outside the jobNarrow the table list

Read the table and column names first, then the counts. Zero is correct when the old string isn't in the database.

Replacement report interpretation

The preview can't test rendered pages, and the real command runs against whatever the database holds at that moment.

Apply only the replacement you have reviewed

WordPress replacement command

When the preview shows the tables and counts you expected, remove --dry-run. Keep the same installation, old and new strings, table restrictions or other scope flags, and column exclusions.

wp --path=/path/to/site search-replace \
  'https://old.example' 'https://new.example' \
  --skip-columns=guid

Record the command you ran, the installation, the values and scope, and the result.

Write transformed SQL to a file instead

With --export, wp search-replace writes transformed SQL to a file and leaves the source database unmodified.

wp --path=/path/to/site search-replace \
  'https://old.example' 'https://new.example' \
  --skip-columns=guid \
  --export=/secure-backups/transformed.sql

This file doesn't replace the pre-change backup. The output directory must exist and accept writes. The official command reference describes --old and --new as options outside a stable release, so these examples use the established positional strings.

Transformed SQL export

Look for old URLs that remain in the database

WordPress residual URLs

After the replacement, search the database for old references that remain. wp db search does this without writing anything:

wp --path=/path/to/site db search \
  'https://old.example' --stats

By default it searches registered WordPress tables and is case-insensitive, so a match can differ in letter case from your input. Look at the stored value before deciding which reference survived.

If the replacement covered a wider authorized scope, extend the search with --all-tables-with-prefix, --all-tables, or --network, as applicable.

You're done when no unwanted old URLs remain. A leftover match points to one of these:

  • Active content or option: A page, link, or setting still uses the old location.
  • Plugin storage outside the first scope: A table you intended to change wasn't part of the first run.
  • Preserved identifier: An old-looking guid stays valid because it identifies the post.
  • Historical or unrelated record: A log or archived value correctly refers to the former address.
Database search matches

Check the live pages, admin area, and generated files

WordPress page verification

Check the site as visitors see it. Open representative pages at the new address, including pages that had internal links or media, and test navigation, images, and the WordPress administration area.

search-replace can't modify file-based URLs or generated CSS, so page builders need their own check. A migrated Elementor page, for example, can show correct database values and still load a background image from the old hostname through generated CSS.

Elementor: Elementor documents a Replace URL tool and a Clear Files & Data operation for URL and generated-file problems. On an Elementor site, run those tools and do a targeted generated-asset cache refresh before checking the affected page again.

If the old domain still appears, locate its source

Old domain redirects

If the site redirects to its development domain after the database update, find the cause before running anything else. A wider replacement can change unrelated records without touching the redirect source.

After moving a development site to production on shared hosting, another r/Wordpress user described this exact symptom: “However, whenever I try to access the site, it keeps redirecting to the development URL.” (r/Wordpress development URL discussion)

WordPress supports WP_HOME and WP_SITEURL constants in wp-config.php. When defined, they override the corresponding database-stored URL options.

  • The browser sends visitors to the former domain: Find out whether WordPress configuration, the web server, or the hosting platform issues the redirect.
  • The page loads but its assets refer to the former domain: Trace each asset to its content or generated-file source.
  • Database references are already fixed: Inspect the configuration and delivery mechanisms behind the remaining symptom.
Redirect source diagnosis

When a hosted tool or plugin is the better route

WordPress replacement methods

If you can't open an SSH session, your hosting account can still offer search-and-replace controls. WP Engine and Kinsta describe provider-specific interfaces, and WordPress plugins are another route where the installation permits them.

WP-CLI needs authorized CLI access. A host tool needs a supported function in your hosting account, and a plugin needs WordPress and plugin permissions. WP-CLI gives you documented table and column options, documented handling of serialized values, --dry-run, and an SQL backup you control. Before using a host tool or plugin, confirm that it offers the same four things.

Hosting tool comparison

Restore deliberately if the change has caused damage

WordPress database recovery

Before you restore, consider what changed after the backup was taken. wp db import imports SQL into the configured database, and restoring an earlier dump can overwrite valid later orders, comments, registrations, or edits on an active site.

If you know the mistake and the affected records, a targeted correction can preserve later changes. Otherwise, restore under the site's recovery procedure and bring the database and files into a consistent state.

NoScript Team