Short answer: Drupal does not have a one-click WordPress export. The fastest path is the FG Drupal to WordPress plugin, which connects to your live Drupal database from inside WordPress and pulls nodes, users, taxonomies, and files across in one pass. It handles a basic Drupal 7, 8, 9, or 10 site reasonably well. The hard parts are everything outside the article-and-page model: custom content types with deep field relationships, Views, Panels, Webform submissions, multilingual content, and Drupal Commerce all rebuild in WordPress equivalents. Plan for a weekend if you have under 200 nodes of standard Article/Basic Page content. Plan for four to eight weeks if you have custom content types, multilingual content, or anything beyond a content site.
This guide walks the migration end to end: deciding whether to migrate at all, choosing between the plugin path and a manual SQL-and-CSV path, mapping Drupal’s content model onto WordPress, moving files and images, rebuilding what does not migrate, setting up redirects so you do not lose ranking, and the post-launch checklist that catches the dozen small things that always slip through.
Migration at a glance#
| Phase | What it covers | Time for a 200-node site | Time for a 2,000-node site with custom types |
|---|---|---|---|
| Plan | Inventory content types, fields, users, files; pick hosting; set up staging WP | 3-5 hours | 1-2 weeks |
| Field mapping | Decide how each Drupal content type and field maps to WP post types or ACF fields | 2-4 hours | 1-2 weeks |
| Run migration tool | FG Drupal to WordPress (or manual SQL export) | 30-90 minutes | 4-12 hours, often run several times |
| Files and images | Move
sites/default/files
into
wp-content/uploads
, fix URLs | 1-3 hours | 1-3 days |
| Rebuild Views, blocks, Panels | Translate each Drupal View into a WP query, widget, or shortcode | 4-8 hours | 2-4 weeks |
| Redirects and URL aliases | Build the 301 map from Drupal aliases to WordPress permalinks | 2-4 hours | 3-5 days |
| Post-launch | Test, fix broken links, submit to Search Console, verify analytics | 2-3 hours | 1 week |
The article and page transfer is the fast part. The time goes into mapping Drupal’s structured content into WordPress’s flatter model, then rebuilding everything the migration tool cannot touch.
Before you start: should you even migrate?#
Drupal is not a bad CMS, and migrating off it is real work. The cases where WordPress is genuinely the better fit:
- The team writing content is non-technical, the editorial workflow is simple, and Drupal’s admin UI has become a drag on day-to-day publishing.
- The plugin or theme you actually need only exists for WordPress. WooCommerce, LearnDash, MemberPress, and most page builders have no real Drupal equivalent.
- You cannot find or keep affordable Drupal developers. WordPress’s developer pool is larger and cheaper.
- You are on Drupal 7, which reached end of life in January 2025, and rather than rebuild on Drupal 10 you would rather move sideways.
The cases where you should stop and reconsider:
- Your site is a complex content architecture where the data model is the product. Academic catalogs, government services, multilingual knowledge bases with thousands of cross-referenced nodes, and per-role editorial workflows are usually easier to maintain in Drupal than to recreate in WordPress with ACF and PublishPress.
- You rely on Drupal-specific modules like Workbench Moderation, Group, Organic Groups, or complex Views with relationships and contextual filters. WordPress can approximate these, but you will write a lot of glue code.
- Your team includes Drupal developers and no WordPress developers. The cost of retraining or rehiring usually outweighs the cost of staying.
WordPress vs Joomla vs Drupal walks through the trade-offs in more detail if you are still on the fence.
If WordPress is the right destination, keep going.
What migrates cleanly and what does not#
What the FG Drupal to WordPress plugin transfers#
- Articles and Basic Pages, including title, body, author, publish date, and status (published, draft)
- Standard Drupal users (username, email, hashed password, role)
- Categories and tags (Drupal taxonomies map to WP categories and tags)
- Featured images attached to nodes
- File attachments referenced in nodes
- URL aliases (so you can build the redirect map)
- Comments, if you use Drupal core comments
- Custom content types as standard WP posts, or as custom post types if you have Pro
What you rebuild manually#
- Views (every list, grid, slider, or query-based block on your site)
- Panels and Panelizer layouts
- Custom blocks and block placements
- Menus and menu structure
- Webforms and form submissions
- Multilingual content from Entity Translation or Content Translation modules (Pro can handle this with WPML or Polylang on the destination side, with manual cleanup)
- Drupal Commerce products, orders, and customers
- Module-specific data (Group memberships, Workbench workflow states, Flag entries, Voting API data)
- Custom theme styling
- Drupal-side 301 redirects from the Redirect module (you re-import these)
- Field collections, paragraphs, and other entity-on-entity structures (these flatten or get stitched into post content)
For a brochure site or a content-only Drupal install, the plugin handles 80% of the work and you rebuild the theme and menus in WordPress. For a multilingual e-commerce site with Views-driven landing pages and Group-based access control, the plugin is a starting point and you will spend weeks rebuilding.
Step 1: Set up WordPress on staging before you touch the live Drupal site#
Do the entire migration into a staging WordPress install. Never run a migration tool against your production database, even read-only, without a fresh backup first.
Set up a staging WordPress install. Pick hosting, install WordPress at
staging.yournewdomain.com
or similar, and configure it before importing anything. How to create a WordPress staging site covers the staging pattern end to end.
Do these before running any migration tool:
- Set permalinks (Settings > Permalinks). Pick the format that gets closest to your Drupal URL aliases. If your Drupal aliases are
/article/my-post-title, use/%category%/%postname%/. If they are flat slugs like/my-post-title, use/%postname%/. The closer the match, the shorter your redirect map. - Install Advanced Custom Fields (ACF). If your Drupal content types have custom fields, you will need ACF (or Meta Box) to hold them on the WP side. The free version is fine to start.
- Pick a theme. Drupal’s theme will not carry over. WordPress’s modern block themes (Twenty Twenty-Five, Kadence, Astra, GeneratePress) are good starting points. How to change, install, and customize a WordPress theme covers the theme setup.
- Configure WordPress’s basic settings: site title, tagline, time zone, default category, default user role. None of this carries from Drupal.
- Install Yoast SEO or Rank Math. You will need it for meta descriptions, sitemap generation, and the redirect map.
Step 2: Inventory your Drupal site before you export anything#
The most common reason migrations go badly is that someone runs the migration tool before understanding what is actually on the source site. Spend an hour on this inventory. It will save you days later.
In Drupal, list:
- Content types. Structure > Content types. For each one, note: how many nodes, what fields it has, whether it should become a Post, a Page, or a Custom Post Type in WordPress.
- Taxonomies. Structure > Taxonomy. Map each vocabulary to a WordPress taxonomy (categories, tags, or a custom taxonomy).
- Custom fields. Structure > Content types > [type] > Manage fields. List every field on every content type. Decide which become ACF fields, which become standard WP post fields, and which become post meta you do not need anymore.
- Views. Structure > Views. List every View you have built. For each one, note where it is displayed (page, block, embed) and what it does. Every one will be rebuilt in WordPress.
- Menus. Structure > Menus. Export each menu structure. You will recreate them by hand.
- Modules in use. Extend. List the contrib modules you actually rely on. Find WordPress equivalents now, not after the migration.
- URL aliases. Configuration > URL aliases (or check the
url_aliastable directly). Export the full list. This is your redirect map source. - Users and roles. People > Roles. Decide which Drupal roles map to which WordPress roles. WordPress’s default roles are Administrator, Editor, Author, Contributor, Subscriber.
Save all of this to a single document. You will reference it constantly.
Step 3: Choose the migration path#
There are two realistic paths. The right one depends on the complexity of your site.
Path A: FG Drupal to WordPress plugin#
For most sites, this is the right choice. The free version handles Drupal 6, 7, 8, 9, and 10. It transfers articles, pages, users, taxonomies, featured images, and basic file attachments. The Premium version adds custom content types, custom fields, Views translation, Webform import, and Drupal Commerce-to-WooCommerce data movement.
The plugin runs from inside your destination WordPress install. You give it your Drupal database credentials (read-only is fine), and it pulls data over the network. It can resume if it fails partway through, and it can run incremental updates if you keep publishing on Drupal during the migration.
Install it from the WordPress plugin directory, go to Tools > Import > Drupal, and step through the configuration wizard:
- Enter your Drupal database host, name, user, password, and table prefix (usually
drupal_or empty). - Test the connection. If it fails, your firewall probably blocks remote MySQL. You will need to either open the port temporarily, run the import from a server that can reach the Drupal database, or dump-and-restore the Drupal database into a database WordPress can reach.
- Choose what to import. Articles, pages, users, taxonomies, media, comments.
- Map Drupal content types to WordPress post types.
- Click “Start / Resume the import.” This will take anywhere from a few minutes to several hours depending on size.
If the import times out or PHP runs out of memory, see WordPress maximum execution time exceeded and the standard memory-limit fix in PHP memory exhausted. On most hosts you can bump the limits temporarily for the migration window and put them back afterwards.
Path B: Manual SQL and CSV approach#
If your site is small and you have technical comfort, you can skip the plugin entirely. Export Drupal’s
node
,
node_field_data
,
users_field_data
,
taxonomy_term_field_data
, and field tables to CSV, transform them with a script, and import via WP-CLI:
wp post create --post_type=post --post_title="..." --post_content="..." --post_date="..." --post_status=publish
This is more control but more work. Use it when:
- The plugin trips on a specific custom content type and you only have one or two
- You want to flatten the migration into a one-time CSV that you can hand-edit before importing
- You have entity-on-entity relationships (field collections, paragraphs) that need stitching into post content
For most sites, Path A is faster.
Step 4: Move the files and fix the image problem#
The plugin transfers featured images and file attachments by URL. WordPress fetches each file from your Drupal site and stores it in the WordPress media library. That works fine if your Drupal site is reachable from the WordPress server during migration.
There is a trap: the URLs that get rewritten in post bodies need to match the new location. Drupal stores image URLs as
/sites/default/files/inline-images/photo.jpg
. WordPress wants them at
/wp-content/uploads/2024/03/photo.jpg
. The plugin handles this for fields it knows about, but inline image references inside the body HTML are easy to miss.
After import, install Auto Upload Images (https://wordpress.org/plugins/auto-upload-images/). Open each post and save it. The plugin scans for any remaining external image URL in the post body, downloads it into the media library, and rewrites the reference. Run this on every post before you take Drupal offline.
For very large sites, you can copy
sites/default/files
directly over to
wp-content/uploads
via SFTP or rsync, then rewrite the URLs in the database with WP-CLI:
wp search-replace 'sites/default/files' 'wp-content/uploads' --skip-columns=guid --dry-run
Remove
--dry-run
once you have confirmed the count of replacements looks right. Always run with
--skip-columns=guid
so you do not break the GUID column (which WordPress uses internally and should never change). See why most WordPress migrations fail for why naive find-and-replace on a serialized PHP value corrupts the database, and why WP-CLI’s search-replace is safe and find-and-replace in phpMyAdmin is not.
Step 5: Rebuild Views, Panels, and blocks#
This is where the time goes. Every Drupal View becomes something else in WordPress. There is no one-to-one tool that converts Views to WordPress.
For each View in your inventory, decide what it becomes:
- Latest-articles block on the homepage. Becomes a Latest Posts block in Gutenberg, or a
WP_Queryloop in your theme template, or a Recent Posts widget. - Author archive page with custom layout. Becomes a custom author template (
author.php) in your theme, withWP_Queryfiltering by author. - Filtered listing with exposed filters. A WordPress plugin like FacetWP or SearchWP handles exposed filtering. For simpler cases, a custom shortcode with
WP_Queryis enough. - Slider or carousel pulling from a content type. Use a slider plugin (Smart Slider, Soliloquy) that supports dynamic content from posts.
- Calendar view of events. The Events Calendar plugin.
Panelizer and Panels-based layouts have no direct WordPress equivalent. Most teams rebuild these as Gutenberg block patterns, as block themes’ template parts, or with a page builder (Elementor, Bricks, Kadence Blocks). Pick one approach and stick with it.
Custom blocks placed via Drupal’s Block UI become widgets, Gutenberg blocks, or theme template parts depending on where they appear.
Step 6: Decide on your permalink structure and write the redirect map#
Drupal’s URL aliases probably look like one of these patterns:
-
/article/post-title(content-type prefix + slug) -
/news/2024/post-title(section + year + slug) -
/post-title(flat slug, via Pathauto with bare slugs)
Pick a WordPress permalink structure that gets you close to the source. Settings > Permalinks > Custom Structure:
- For
/post-titleDrupal aliases, use/%postname%/. - For
/article/post-title, you can either change to/%postname%/and redirect, or use/%category%/%postname%/if every article is in one category. - For
/news/2024/post-title, use/%year%/%postname%/and accept that the section prefix is gone.
Whatever you pick, every old Drupal URL needs a 301 redirect to its new WordPress URL. This is non-negotiable for SEO. Without redirects, Google sees your old URLs as 404s and your rankings collapse.
Export the URL aliases from Drupal:
SELECT source, alias FROM url_alias;
(In Drupal 8+ the table is
path_alias
and the columns are
path
and
alias
.)
Each row becomes a redirect rule. Install the Redirection plugin by John Godley in WordPress. Import the redirect map as a CSV, or paste in batches. How to set up 301 redirects in WordPress covers the redirect plugin setup.
If your alias count is very high (tens of thousands), do the redirects in the web server config instead. Nginx redirect maps are faster than a PHP plugin at high volume.
Step 7: Migrate users and force a password reset#
Drupal and WordPress both use bcrypt-family password hashing, but the salt formats are different. The FG Drupal to WordPress plugin imports users with their hashed passwords, but the hashes will not validate against the WordPress login flow.
The clean fix: force every user to reset their password on first login. After migration:
- Email all users that the site has moved and they need to reset their password.
- Send them to
/wp-login.php?action=lostpasswordto set a new password.
A more user-friendly fix is the Password Hash Compatibility plugin or a custom
authenticate
filter that validates the Drupal hash, then re-hashes with WordPress’s format on first successful login. This requires custom code and is worth it only for sites with thousands of active users where a forced reset would generate too many support tickets.
Map Drupal roles to WordPress roles deliberately. Drupal’s “administrator” maps to WordPress’s “Administrator.” Drupal’s “editor” maps to “Editor.” Drupal’s “authenticated user” maps to “Subscriber.” Any custom Drupal roles need a decision: collapse into an existing WordPress role, or create a custom one with the Members or User Role Editor plugin.
Step 8: Move the domain and cut over DNS#
Once staging looks good, you have two paths to launch.
Path A: Transfer the domain to a new registrar at the same time as launch. Unlock the domain at your current registrar, get the EPP/auth code, initiate the transfer at the new registrar. Allow five to seven days for the transfer to complete. Update DNS to point to your new WordPress host. This is the cleanest path long-term but adds time pressure.
Path B: Keep the domain at the current registrar, only change DNS. At your DNS provider, update the A record (and AAAA if applicable) to point to the new WordPress host’s IP. TTL on the old record determines how fast the change propagates – lower the TTL to 300 seconds a day or two before launch so the cutover is fast.
If you are also changing the domain name (
olddomain.org
to
newdomain.com
), you have additional redirect work. How to change your WordPress domain name covers the wp_options, wp-config, and serialized-data steps.
After DNS cuts over:
- SSL certificate: provision a new cert for the WordPress site. Let’s Encrypt via Certbot is free and standard.
- Confirm
https://works without warnings. - Confirm
wwwand non-wwwboth resolve and one redirects to the other (pick one and stick with it).
Step 9: Post-launch checklist#
In the first hour after cutover:
- Test in incognito. Open the homepage, an article, a category page, the search results, and the contact form in a private browsing window. Logged-in browser caching hides problems.
- Test five random redirects. Pick five old Drupal URLs from your aliases list. Visit each one. Confirm it 301-redirects to the right WordPress URL.
- Install Broken Link Checker (the plugin or the standalone tool by W3C). Run it. Fix any internal links that point at old Drupal paths.
- Submit the new sitemap to Google Search Console. Yoast or Rank Math generates the sitemap at
/sitemap.xml. Add it to GSC and request indexing. - Confirm analytics is still firing. If you used Drupal’s Google Analytics module, you need to re-add the GA snippet in WordPress (most SEO plugins or a dedicated header-and-footer plugin handles this).
- Test the contact form and any user-facing forms. Drupal Webforms do not migrate. You rebuilt them in WPForms or Gravity Forms or Contact Form 7. Confirm submissions arrive in the inbox you expect.
- Test the search results page. WordPress core search is weaker than Drupal’s. Many migrating sites add Relevanssi or SearchWP to make search usable.
- Verify favicon, Open Graph tags, and Twitter Card markup. These are easy to miss because they require a theme refresh and a meta plugin (Yoast handles OG/Twitter).
- Export old analytics data. Pull a 12-month report from your old GA property so you have a baseline. Search Console data does not export cleanly but you can take screenshots of key reports.
In the first week:
- Watch Search Console daily for new 404s. Each one is a missed redirect. Add it to the Redirection plugin.
- Watch your server logs for slow queries. The new WordPress site has a different query profile than Drupal, and you may need an object cache (Redis, Memcached) if the database is under load.
- Watch your email deliverability. Drupal often sends transactional email via the server’s
mail(). WordPress does too, and it is just as unreliable. Add an SMTP plugin (WP Mail SMTP) and route email through a real provider (Postmark, SendGrid, Amazon SES, SMTP2GO).
In the first month:
- Cancel your Drupal hosting once you have confirmed nothing is calling back to it (images, AJAX, embedded forms).
- Archive a complete Drupal backup somewhere safe. You will not need it once the new site has run clean for a month, but it costs nothing to keep.
- Decide on the long-term Drupal asset URLs. If you had images at
/sites/default/files/...and other sites embed those URLs, decide whether to keep a static redirect from the old paths or to leave them dead.
Common mistakes that bite#
- Migrating before mapping content types. The plugin will happily pull everything across with default mappings, but you will end up with a WordPress site that mirrors Drupal’s structure poorly. Spend the time on the field mapping document.
- Skipping the staging step. Migrating directly to production means every problem affects real users. Always migrate into staging, then push.
- Forgetting Views. First-time Drupal-to-WP migrators are often surprised that no Views are present after migration. Views are queries; they have no on-disk content. Every one must be rebuilt.
- Naive find-and-replace on serialized data. Drupal stores some data as serialized PHP arrays. WordPress does too. Running find-and-replace in phpMyAdmin or with raw SQL corrupts these. Always use WP-CLI’s
wp search-replacewith--skip-columns=guid. - Not exporting URL aliases before migrating. The plugin transfers nodes but not always the alias map cleanly. Run the SQL export of the
url_alias(orpath_alias) table separately so you have an authoritative source for redirects. - Letting the redirect plugin handle 50,000 rules. PHP-level redirect plugins get slow at scale. For sites with tens of thousands of redirects, move the redirect map into the web server config.
- Trying to match Drupal pixel-for-pixel. The point of moving to WordPress is to use WordPress. Rebuilding Drupal’s exact layout in WordPress costs weeks and produces a fragile result. Pick a WordPress theme that works, then adapt your content to it.
- Migrating user passwords and assuming they work. Drupal and WordPress hash format differs. Plan for a forced password reset or a compatibility plugin.
- Forgetting to test the search page. WordPress core search is much weaker than Drupal’s. If search was important on the Drupal site, you need Relevanssi, SearchWP, or Algolia in WordPress.
- Cancelling Drupal hosting too early. Wait at least 30 days after the WordPress site is live and stable. Things break, and a backup-restore of the Drupal site can save you.
How long does it take#
Realistic timelines, assuming one or two people working on it and that the source Drupal site is in reasonable shape:
| Site type | Migration tool time | Rebuild time | Total elapsed |
|---|---|---|---|
| Brochure site, under 50 nodes, no custom types | 30 minutes | 1-2 days | 2-4 days |
| Blog, 200-500 posts, standard taxonomies | 1-2 hours | 1 week | 1-2 weeks |
| Content site, custom content types, several Views | 2-4 hours | 2-3 weeks | 3-5 weeks |
| Multilingual site, 1,000+ nodes | 4-8 hours, run multiple times | 3-4 weeks | 5-8 weeks |
| Drupal Commerce store with products and orders | 4-8 hours for content; commerce data is partly manual | 4-6 weeks | 8-12 weeks |
| Enterprise site with Workbench, Group, custom modules | Plugin gets you to 60%; the rest is bespoke | 2-4 months | 3-6 months |
If your timeline is shorter than this, you are not migrating, you are rebuilding. That is a valid choice for older sites where the content is small enough that rewriting it in WordPress is easier than transferring it.
What about going the other direction#
A small share of searches go the other way: “migrate WordPress to Drupal.” It happens, but it is rare and almost always for a specific structural reason – usually that the WordPress site has outgrown its content model and needs Drupal’s content architecture. The path is the same in reverse: there is a Drupal contrib module called WordPress Migrate that pulls posts, users, and media in. Everything else rebuilds. If you are reading this article, you are almost certainly going the more common direction.
Summary#
A Drupal to WordPress migration is a real project, not a click. The mechanical content transfer is straightforward with the FG Drupal to WordPress plugin. The rebuild is where the weeks go – Views, Panels, custom fields, multilingual content, and any module-specific data all have to be redone in WordPress equivalents. Plan the content type mapping before you run any tool, migrate into staging not production, build the redirect map from your URL aliases so you do not lose SEO, force password resets on users, and budget realistically for the rebuild. Done with patience, the destination is a faster site, a cheaper developer pool, and a much larger plugin ecosystem.