To migrate a WordPress site to a new domain, you copy the files and the database to the new place, replace the old domain in the database, add 301 redirects from the old domain, and tell Google about the move. You can do all of this without a migration plugin. This guide shows each step and the database queries.

Migrate WordPress site to new domain: quick answer

  1. Back up the files and the database.
  2. Copy the site files and import the database on the new domain.
  3. Update wp-config.php if the database name or user changed.
  4. Replace the old domain in the database. Use WP-CLI if you can (safe). Use SQL only for the simple, plain-text columns.
  5. Save Settings > Permalinks and check the site.
  6. Add 301 redirects from the old domain to the new domain.
  7. Tell Google with the Change of Address tool, if it fits your move.

Before you migrate WordPress site to new domain

  • Make a full backup of the files and the database, and keep a copy on your own computer.
  • Write down the exact old and new address, with https or http, and with or without www. A wrong match means nothing gets replaced.
  • Find your table prefix. Open wp-config.php and look for $table_prefix. This guide uses wp_. If yours is different, use yours in every query.
  • If you can, try the whole move on a copy first.

Step 1: Copy the files and the database

  1. Copy the whole WordPress folder (or at least wp-content and wp-config.php) to the new hosting.
  2. In phpMyAdmin on the old host, select the database and use Export. Then import the file into a new database on the new host.
  3. Open wp-config.php on the new host. Set DB_NAME, DB_USER, DB_PASSWORD and DB_HOST for the new database.
wp-config.php showing the database name, user and host settings

Why you should not run a plain SQL replace everywhere

WordPress stores some data as PHP serialized text. It looks like s:5:"hello", where the number is the length of the text. If you replace a domain inside such a value and the length changes, the stored length is wrong and WordPress can no longer read that value. This can break widgets, theme settings and plugin settings.

The first version of this post replaced the domain in every row of wp_options and wp_postmeta with plain SQL. That is risky, so this guide now uses a safer way.

Step 2: Migrate WordPress site to new domain with WP-CLI (recommended)

WP-CLI is the official command line tool for WordPress. Its search-replace command handles serialized data. You need SSH access to the server and WP-CLI installed. Ask your host if you are not sure you have both.

Always run a dry run first. It shows what would change and saves nothing.

wp search-replace 'https://old_site_domain' 'https://new_site_domain' --skip-columns=guid --dry-run

If the numbers look right, run it again without --dry-run:

wp search-replace 'https://old_site_domain' 'https://new_site_domain' --skip-columns=guid

Then do the same for the old http address, if your old site ever used it:

wp search-replace 'http://old_site_domain' 'https://new_site_domain' --skip-columns=guid

The part --skip-columns=guid leaves the guid column alone. The guid is an ID for each post, not a normal link, so it is better not to change it. See the WP-CLI search-replace documentation for all options.

Step 3: Migrate WordPress site to new domain with SQL (no WP-CLI)

If you cannot use WP-CLI, you can use phpMyAdmin. Do it only on columns that hold plain text, not serialized data.

  1. Open phpMyAdmin.
  2. Select the database.
  3. Go to the SQL tab.
  4. Paste the query.
  5. Execute the query with the Go button.
phpMyAdmin SQL tab used to change the old domain to the new domain in a WordPress database
phpMyAdmin – Database queries to migrate the site to the new domain

Safe query 1: the site address

These two settings are plain text and safe to change:

UPDATE wp_options SET option_value = 'https://new_site_domain' WHERE option_name IN ('home', 'siteurl');

Safe query 2: links inside post content

Post content is normal text, so this replace is usually safe. The first line changes the https links, the second line changes old http links:

UPDATE wp_posts SET post_content = REPLACE(post_content, 'https://old_site_domain', 'https://new_site_domain');
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://old_site_domain', 'https://new_site_domain');

Some blocks and page builders store links with escaped slashes, like https:\/\/old_site_domain. If the check in Step 5 still finds the old domain in post content, run this too:

UPDATE wp_posts SET post_content = REPLACE(post_content, 'https:\\/\\/old_site_domain', 'https:\\/\\/new_site_domain');

Careful: the rest of wp_options and wp_postmeta

These two tables hold many serialized values. First look at which rows contain the old domain:

SELECT option_name, LEFT(option_value, 60) FROM wp_options WHERE option_value LIKE '%old_site_domain%';
SELECT meta_key, LEFT(meta_value, 60) FROM wp_postmeta WHERE meta_value LIKE '%old_site_domain%';

If a value starts with a:, s:, O: or i:, it is serialized. Do not use a plain replace on it. Use WP-CLI (Step 2) or a search-replace tool that supports serialized data. Plain values, such as a single URL, can be replaced with a normal UPDATE ... REPLACE(...) query.

[SCREENSHOT 2: phpMyAdmin result of the SELECT query on wp_options (your own test). Alt text: phpMyAdmin result listing options rows that contain the old domain. DELETE THIS BOX after adding the real image.]

Do not change the guid

The first version of this post also replaced guid. You do not need to do that. Leave it as it is.

Step 4: Update the Yoast SEO entries

If you use Yoast SEO, it keeps its own copy of your page addresses in the wp_yoast_indexable table. The canonical address matters, because search engines use it to identify your page and to avoid duplicate content. These columns are plain text:

UPDATE wp_yoast_indexable SET permalink = REPLACE(permalink, 'https://old_site_domain', 'https://new_site_domain');
UPDATE wp_yoast_indexable SET twitter_image = REPLACE(twitter_image, 'https://old_site_domain', 'https://new_site_domain');
UPDATE wp_yoast_indexable SET open_graph_image = REPLACE(open_graph_image, 'https://old_site_domain', 'https://new_site_domain');

The column open_graph_image_meta can hold data in JSON form. Look at one row with a SELECT first, then replace carefully. After the move, open a post, view the page source and check that the canonical link and og:image show the new domain.

Step 5: Check that nothing is left

Run these queries. The first one should return 0. The other two should return 0 once the serialized rows are also fixed with WP-CLI.

SELECT COUNT(*) FROM wp_posts WHERE post_content LIKE '%old_site_domain%';
SELECT COUNT(*) FROM wp_options WHERE option_value LIKE '%old_site_domain%';
SELECT COUNT(*) FROM wp_postmeta WHERE meta_value LIKE '%old_site_domain%';

Then log in and save Settings > Permalinks once. This refreshes the rewrite rules. Click through the home page, a post, a category page and the contact page. Check that images, menus and forms work.

[SCREENSHOT 3: the check query result showing 0 (your own test). Alt text: phpMyAdmin result showing 0 rows with the old domain. DELETE THIS BOX after adding the real image.]

Step 6: Redirect the old domain to the new domain (301)

A 301 redirect tells visitors and Google that the move is permanent. On the OLD site, add this to .htaccess, above the # BEGIN WordPress block. It works on Apache and LiteSpeed servers. Back up the file first.

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?old_site_domain$ [NC]
RewriteRule ^(.*)$ https://new_site_domain/$1 [R=301,L]

This keeps the same path: old_site_domain/my-post/ goes to new_site_domain/my-post/. Keep the redirects for at least a year, or longer if you can.

Step 7: Tell Google about the move

  1. Add and verify BOTH the old and the new site in Google Search Console.
  2. Make sure the 301 redirects work (Step 6).
  3. Use the Change of Address tool. Google says to open it in a property at the domain level (like example.com, not example.com/path). It is meant for moves from one domain or subdomain to another.
  4. Submit the sitemap of the new site in the new property.

See Google’s page Change of Address tool for the current requirements (checked 28 Oct 2026). A site move can make rankings dip for a while, so watch Search Console over the next weeks.

Migrate WordPress site to new domain with a plugin

If you do not want to touch the database, a search-replace plugin such as Better Search Replace can do Step 2 from the dashboard, and it supports serialized data. Back up first and use its dry run option.

Common problems after you migrate a WordPress site to a new domain

ProblemLikely causeFix
Site redirects back to the old domainhome and siteurl still hold the old addressRun safe query 1, or set them in wp-config.php
Images do not showOld links or escaped slashes still in the contentRun the check queries and replace the escaped version too
Widgets or theme settings are goneA plain SQL replace broke serialized dataRestore the backup and use WP-CLI instead
404 on all pages except the home pageRewrite rules are oldSave Settings > Permalinks
Mixed content warningSome links still use httpReplace the http address too
Yoast shows the old canonical addressThe Yoast table was not updatedRun the Yoast queries and clear all caches

FAQ: migrate WordPress site to new domain

Can I migrate a WordPress site to a new domain without a plugin?
Yes. Copy the files, import the database, replace the old domain in the database, then add 301 redirects. WP-CLI makes the database step safe.

Is it safe to run a SQL REPLACE on the whole WordPress database?
No. Some values are serialized, and a replace that changes the text length can corrupt them. Use WP-CLI search-replace, or limit SQL to plain text columns.

Do I need to change the guid column?
No. Leave it unchanged. The WP-CLI examples skip it too.

Will I lose my Google rankings if I move to a new domain?
Rankings can dip for a while after a move, and nobody can promise how long. Correct 301 redirects and the Change of Address tool help Google follow the move.

Next steps

One Response

Leave a Reply

Your email address will not be published. Required fields are marked *