Skip to main content
Blog|
How-to guides

How to migrate from Joomla to WordPress

|
May 14, 2026|20 min read
HOW-TO GUIDESHow to migrate from Joomla toWordPressHOSTNEYhostney.comMay 14, 2026

Short answer: Joomla and WordPress have different content models, so there is no one-click export. The fastest path is the FG Joomla to WordPress plugin, which connects to your Joomla database from inside WordPress and pulls articles, categories, users, and media across in a single pass. It handles a basic Joomla 1.5, 2.5, 3.x, 4.x, or 5.x site reasonably well. The hard parts are everything outside the article-and-category model: Modules, menu structure, K2 or EasyBlog content, JReviews directories, VirtueMart or HikaShop stores, multilingual content from Joomla’s core Languages, and any third-party extension data. Plan for a long weekend on a 200-article content site. Plan for three to six weeks if you have K2, a store, or multilingual content.

This guide covers the full migration end to end: deciding whether to migrate at all, mapping Joomla’s content model onto WordPress, running the migration tool, handling K2 and EasyBlog content separately, moving images and fixing the URL references the importer misses, rebuilding Modules and menus, building the SEF-aware redirect map, and the post-launch checklist that catches what slips through.

Migration at a glance#

PhaseWhat it coversTime for a 200-article siteTime for a 2,000-article site with K2 or commerce
PlanInventory content, extensions, users, SEF URL config; pick hosting; set up staging WP3-5 hours1-2 weeks
Field mappingDecide how Joomla categories, articles, K2 items, and any extension data map to WP2-4 hours3-7 days
Run migration toolFG Joomla to WordPress (or K2/EasyBlog companion plugins)30-90 minutes4-10 hours, often run several times
Images and mediaFix images/ references, pull external images into WP media library1-3 hours1-3 days
Rebuild Modules and menusTranslate each Joomla Module into a WP widget, block, or shortcode4-8 hours1-3 weeks
Redirects and SEF URLsBuild the 301 map from Joomla’s SEF aliases to WordPress permalinks2-4 hours2-5 days
Post-launchTest, fix broken links, submit to Search Console, verify analytics2-3 hours1 week

The content transfer is the fast part. The rebuild work is where the time goes – because Joomla’s Modules, Menu Manager, template overrides, and any extension-specific data have no native WordPress equivalent and have to be recreated by hand.

Before you start: should you even migrate?#

Joomla is not a bad CMS, and migrating off it is real work. The cases where WordPress is genuinely the better fit:

  • You are running Joomla 3, which reached end of life in August 2023. The platform is no longer maintained for security, and rather than rebuild on Joomla 4 or 5 you would rather move sideways to WordPress.
  • The extension you actually need only exists for WordPress. WooCommerce, LearnDash, MemberPress, Elementor, and most page builders have no real Joomla equivalent.
  • You cannot find or keep affordable Joomla developers. The Joomla developer pool has shrunk meaningfully in recent years.
  • Your team writes content and the Joomla admin’s complexity is slowing publishing. WordPress’s editor is easier for non-developers.

The cases where you should stop and reconsider:

  • You rely on Joomla’s core multilingual system and have hundreds of translated articles. WordPress can do multilingual with WPML or Polylang, but the migration is harder than the rest of the content because Joomla’s language associations are not native to WordPress.
  • You rely on Joomla’s granular ACL with custom user groups and view-level permissions. WordPress’s default role model is much simpler; you will need PublishPress Capabilities or Members plus custom code to approximate it.
  • You have a heavy K2-based site with categories, custom fields, additional galleries, and tag clouds tied to K2’s data model. K2 migrates to WordPress but rarely cleanly.
  • Your store runs on VirtueMart with custom payment plugins. WooCommerce is the WordPress equivalent, but products, orders, and customers do not migrate automatically. You are functionally rebuilding the storefront.

WordPress vs Joomla vs Drupal walks through the trade-offs in more detail if you are still on the fence. If you have decided to move, keep going.

What migrates cleanly and what does not#

What the FG Joomla to WordPress plugin transfers#

  • Articles (title, body, intro text, full text, publish date, author, state)
  • Joomla categories (mapped to WP categories)
  • Users (username, email, hashed password, basic role)
  • Featured images and intro images attached to articles
  • Image references inside article body content (with caveats – see Step 4)
  • Tags (if you are on Joomla 3.1 or later where tags exist as a core feature)
  • Comments, if you use JComments or a core comments solution that stores in the article (rare)
  • SEF URL aliases (so you can build the redirect map)

What you rebuild manually#

  • Modules and module positions (every block on every Joomla template position)
  • Menu Manager structure (Joomla’s menus drive layout in ways WordPress menus do not)
  • Template overrides, custom CSS, and any HTML in template files
  • K2 articles, K2 categories, and K2 extra fields (separate migration; see Step 3)
  • EasyBlog or other third-party blog component content (separate migration)
  • VirtueMart, HikaShop, or J2Store products, orders, and customers
  • JReviews directories and review data
  • JEvents or JEvents Pro event data
  • Sh404SEF or Route 66 advanced SEF configurations (you re-build redirects from the alias table)
  • Custom fields added in Joomla 3.7+ (Pro versions of FG handle some)
  • Multilingual content from core Joomla Languages (Pro versions handle some; expect manual cleanup either way)
  • Component-specific data (DJ-Classifieds, Phoca Gallery, ChronoForms submissions)
  • Banner and contact components
  • Template parameter overrides and Module Class Suffix styling

For a content-only Joomla site with core articles in core categories, the plugin handles 80% of the work and you rebuild the template and menus in WordPress. For a K2-driven multilingual site with VirtueMart and JReviews, the plugin is a starting point and you will spend weeks rebuilding.

Step 1: Set up WordPress on staging before you touch the live Joomla 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 of Joomla 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:

  1. Set permalinks (Settings > Permalinks). Pick the format that gets closest to your Joomla SEF URLs. If Joomla URLs look like /category/article-title , use /%category%/%postname%/ . If you use sh404SEF with flat slugs, use /%postname%/ . The closer the match, the shorter your redirect map.
  2. Install Advanced Custom Fields (ACF). If your Joomla articles use custom fields (Joomla 3.7+ core feature, or K2 extra fields), you will need ACF or Meta Box on the WordPress side. The free version is fine to start.
  3. Pick a theme. Joomla’s template 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 theme setup.
  4. Configure basic WordPress settings: site title, tagline, time zone, default category, default user role. None of this carries from Joomla.
  5. Install Yoast SEO or Rank Math. You will need it for meta descriptions, sitemap generation, and the redirect map.

Step 2: Inventory your Joomla site before you export anything#

The most common reason migrations go badly is that someone runs the migration tool before understanding what is on the source site. Spend an hour on this. It will save you days later.

In your Joomla admin, list:

  • Article count and category structure. Content > Articles, then Categories. Note totals per category. Decide which Joomla categories become WordPress categories versus tags, and whether you want to flatten nested categories.
  • Components in use. Components menu. Note which components hold content – core Content, K2, EasyBlog, VirtueMart, JReviews, JEvents, Phoca Gallery. Each component is its own migration sub-project.
  • Modules. Extensions > Modules. List every Module, its position, and what it does. Each becomes a WordPress widget, Gutenberg block, or shortcode.
  • Menus. Menus > Manage. Export the structure of each menu. You will recreate them by hand in Appearance > Menus on WordPress.
  • Plugins. Extensions > Plugins. List the plugins you actually rely on. Many Joomla plugins are extension hooks (system, content, authentication) with no direct WordPress equivalent.
  • Templates. Extensions > Templates. Note the active template, any template overrides in templates/yourtemplate/html/ , and any custom CSS in template files.
  • Custom fields. Content > Fields. For each field group, note which articles use it. Decide which become ACF fields and which can be dropped.
  • SEF URL settings. System > Global Configuration > Site tab. Note whether Search Engine Friendly URLs and URL Rewriting are on, whether you use the legacy index.php?option= URLs anywhere, and whether sh404SEF or Route 66 is active.
  • Users and groups. Users > Manage and Users > Groups. Decide which Joomla user groups map to which WordPress roles (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 plus a K2-specific variant. The right one depends on what is on your Joomla site.

Path A: FG Joomla to WordPress plugin (core Joomla content)#

For most sites, this is the right starting point. The free version handles Joomla 1.5, 2.5, 3.x, 4.x, and 5.x. It transfers articles, categories, users, featured/intro images, and basic body content. The Premium version adds custom fields, multilingual content, and K2 article import.

The plugin runs from inside your destination WordPress install. You give it your Joomla 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 Joomla during the migration.

Install it from the WordPress plugin directory, go to Tools > Import > Joomla, and step through the wizard:

  1. Enter your Joomla database host, name, user, password, and table prefix (usually jos_ , j25_ , or a custom prefix from your Joomla installation).
  2. Test the connection. If it fails, your firewall probably blocks remote MySQL. Either open the port temporarily, run the import from a server that can reach the Joomla database, or dump-and-restore the Joomla database into a database WordPress can reach.
  3. Choose what to import: articles, categories, users, media, tags.
  4. Map Joomla categories to WordPress categories or tags. This is the moment to clean up the taxonomy if your Joomla categories had drifted over years.
  5. 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 memory limit fix in PHP memory exhausted. Bump the limits temporarily for the migration window and put them back afterwards.

Path B: K2 content via FG Joomla K2 to WordPress#

If your Joomla site uses K2 for articles (which is common – K2 was the dominant content extension for content-heavy Joomla sites for years), the core FG plugin will not see K2 items. K2 stores content in its own tables ( #__k2_items , #__k2_categories , #__k2_tags ), and you need the K2-aware companion module of FG (Premium) or a dedicated K2-to-WP migration extension.

The K2 migration handles:

  • K2 items as WordPress posts
  • K2 categories as WordPress categories
  • K2 tags as WordPress tags
  • K2 extra fields as ACF fields or post meta (depending on how you configure it)
  • K2 image gallery as WordPress media library entries
  • K2 attachments as media library entries with download links

What K2 does not migrate cleanly:

  • K2 user profiles (K2’s user system is separate from Joomla’s)
  • K2 comments (use a separate comment migration or accept the loss)
  • K2 video embeds (Joomla-specific syntax; rewrite as Gutenberg embed blocks)

Plan to run the core FG migration first, then the K2 migration on top.

Path C: Manual SQL and CSV approach#

If your site is small and you have technical comfort, you can skip the plugins. Export Joomla’s #__content , #__categories , #__users , and #__tags tables to CSV, transform with a script, and import via WP-CLI:

wp post create --post_type=post --post_title="..." --post_content="..." --post_date="..." --post_status=publish

This gives you more control but more work. Use it when:

  • You have one custom Joomla component the plugin does not understand
  • You want to flatten the migration into a one-time CSV you can hand-edit before importing
  • You have hundreds of category-rename decisions that are easier to make in a spreadsheet

For most sites, Path A (and Path B for K2 sites) is faster.

Step 4: Fix the image references the importer misses#

The FG plugin transfers featured images and intro images by URL. WordPress downloads each image from your Joomla site and stores it in the WordPress media library. Image references inside article body content are handled less reliably.

Joomla’s typical image storage pattern is:

  • images/articles/photo.jpg (relative paths in article body)
  • images/stories/photo.jpg (legacy Joomla 1.5 location, still common)
  • images/easyblog_images/photo.jpg (EasyBlog images)
  • media/k2/items/cache/photo.jpg (K2 cached images)
  • /wp-content/uploads/2024/03/photo.jpg is where WordPress wants them

The FG plugin rewrites references for some fields it knows about. Inline <img src> inside the body HTML is easy to miss, especially when the Joomla content uses relative paths like <img src="images/articles/photo.jpg"> .

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 WordPress media library, and rewrites the reference. Run this on every post before you take Joomla offline.

For very large sites, copy images/ directly over to wp-content/uploads via SFTP or rsync, then rewrite URLs in the database with WP-CLI:

wp search-replace 'src="images/' 'src="/wp-content/uploads/joomla-images/' --skip-columns=guid --dry-run

Remove --dry-run once you confirm the replacement count looks right. Always use --skip-columns=guid so you do not break WordPress’s GUID column. See why most WordPress migrations fail for why naive find-and-replace in phpMyAdmin corrupts serialized PHP arrays, and why WP-CLI’s search-replace is safe.

Step 5: Rebuild Modules and menus#

This is where the time goes. Joomla’s Modules and Menu Manager drive a lot of the visible layout in ways WordPress’s widgets and menus do not.

For each Module in your inventory:

  • Latest articles in sidebar. Becomes a Latest Posts block in a Gutenberg widget area, or a Recent Posts widget.
  • Login form Module. Becomes the WordPress login form (theme-dependent) or a sidebar widget.
  • Banners Module. Becomes a banner plugin (AdRotate, Advanced Ads) or simple shortcode-based banners.
  • Breadcrumbs Module. Most WordPress themes have built-in breadcrumbs; otherwise Yoast or Rank Math provides them.
  • Custom HTML Module. Becomes a Custom HTML block in a Gutenberg widget area.
  • Menu Module. Becomes a WordPress menu in Appearance > Menus, displayed via theme widget areas or block-based templates.
  • Article category Module. Becomes a WP_Query loop or a category-listing plugin.
  • Search Module. Becomes the WordPress search widget or block.

Joomla’s Menu Manager is structurally different from WordPress menus. In Joomla, the menu item dictates which Module positions show, which view runs, and which template parameters apply. WordPress menus are navigation only – layout decisions live in the theme.

Plan to recreate each Joomla menu structure in Appearance > Menus, and use widget areas, block-based template parts, or a page builder to handle the visual layout differences.

Joomla’s SEF URL structure depends on which extension generates them:

  • Core Joomla SEF: /index.php/category/article-id-article-title (with Search Engine Friendly URLs on)
  • Core Joomla SEF + URL Rewriting: /category/article-id-article-title
  • sh404SEF: anything you configured – often /category/article-title.html
  • Route 66: similar to sh404SEF, configurable patterns

Whatever pattern you have, every old URL needs a 301 redirect to its new WordPress URL. Without redirects, Google sees old URLs as 404s and rankings collapse.

Export the SEF aliases from Joomla. In core Joomla 3+, redirects from #__redirect_links :

SELECT old_url, new_url FROM jos_redirect_links WHERE state = 1;

For sh404SEF aliases, query #__sh404sef_urls (or your sh404SEF table prefix):

SELECT oldurl, newurl FROM jos_sh404sef_urls;

Each row becomes a redirect rule. Install the Redirection plugin by John Godley. Import as 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.

Common Joomla URL traps that bite the redirect map:

  • The Itemid parameter that Joomla sometimes appends ( ?Itemid=123 ). These need to either be stripped in the redirect or accepted as URL parameters.
  • Article IDs in URLs ( /22-article-title ). If you migrate to slug-only permalinks, every numbered URL needs an explicit redirect mapping the ID-prefixed slug to the bare slug.
  • The index.php segment in non-rewritten URLs ( /index.php/category/... ). These need server-level handling.

Step 7: Migrate users and force a password reset#

Joomla and WordPress both use bcrypt-family password hashing, but the salt formats and verification logic are different. The FG 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:

  1. Email users that the site has moved and they need to reset their password.
  2. Send them to /wp-login.php?action=lostpassword to set a new password.

A more user-friendly option is to use a custom authenticate filter that validates the Joomla 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 Joomla user groups to WordPress roles deliberately:

  • Joomla “Super Users” maps to WordPress “Administrator”
  • Joomla “Administrator” maps to WordPress “Editor” (the names are misleading)
  • Joomla “Editor” maps to WordPress “Editor”
  • Joomla “Author” maps to WordPress “Author”
  • Joomla “Registered” maps to WordPress “Subscriber”

Any custom Joomla user groups (with view-level ACL) need a decision: collapse into an existing WordPress role, or create a custom one with PublishPress Capabilities, User Role Editor, or Members.

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 ( oldsite.org to newsite.com ), there is additional redirect work. How to change your WordPress domain name covers the wp_options, wp-config, and serialized-data steps.

After DNS cuts over:

  1. SSL certificate: provision a new cert for the WordPress site. Let’s Encrypt via Certbot is free and standard.
  2. Confirm https:// works without warnings.
  3. Confirm www and non- www both resolve and one redirects to the other (pick one and stick with it).

Step 9: Post-launch checklist#

In the first hour after cutover:

  1. 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.
  2. Test five random redirects. Pick five old Joomla URLs from your alias export. Visit each one. Confirm it 301-redirects to the right WordPress URL.
  3. Install Broken Link Checker (the plugin, or W3C’s standalone tool). Run it. Fix any internal links that still point at old Joomla paths.
  4. 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.
  5. Confirm analytics is firing. If you used a Joomla Google Analytics plugin, you need to re-add the GA snippet in WordPress (most SEO plugins or a dedicated header-and-footer plugin handles this).
  6. Test the contact form and any user-facing forms. Joomla ChronoForms, RSForm, or core contact components do not migrate. You rebuilt them in WPForms, Gravity Forms, or Contact Form 7. Confirm submissions arrive in the inbox you expect.
  7. Test the search results page. Joomla’s core search is comparable to WordPress’s, but if you used a Joomla search extension (Sphinx Search, Smart Search) you will want Relevanssi or SearchWP in WordPress to match.
  8. 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).
  9. 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:

  1. Watch Search Console daily for new 404s. Each one is a missed redirect. Add it to the Redirection plugin.
  2. Watch your server logs for slow queries. The new WordPress site has a different query profile than Joomla, and you may need an object cache (Redis, Memcached) if the database is under load.
  3. Watch email deliverability. Joomla often sends transactional email via PHP 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:

  1. Cancel your Joomla hosting once you have confirmed nothing is calling back to it (images, AJAX, embedded forms).
  2. Archive a complete Joomla backup somewhere safe. You will not need it once the new site has run clean for a month, but it costs nothing to keep.
  3. Decide on the long-term Joomla asset URLs. If you had images at /images/... and other sites embed those URLs, keep a static redirect from the old paths or leave them dead.

Common mistakes that bite#

  1. Forgetting K2. First-time Joomla-to-WP migrators run the FG plugin, see articles imported, and assume the work is done – while K2 items (the actual content on K2-driven sites) sit untouched in the Joomla database. Always check whether K2 is in use before declaring victory.
  2. Skipping the staging step. Migrating directly to production means every problem affects real users. Always migrate into staging, then push.
  3. Mismatching Joomla “Administrator” with WordPress “Administrator.” Joomla “Administrator” is roughly WordPress “Editor” in capability. Joomla “Super User” is WordPress “Administrator.” Get this wrong and you either give too much access or too little.
  4. Naive find-and-replace on serialized data. Joomla stores some data as PHP-serialized arrays (template params, module params). WordPress does too. Running find-and-replace in phpMyAdmin or with raw SQL corrupts these. Always use WP-CLI’s wp search-replace with --skip-columns=guid .
  5. Not exporting URL aliases before migrating. The plugin transfers articles but the alias map needs a separate SQL export. Run it before you take Joomla down.
  6. 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.
  7. Trying to match Joomla pixel-for-pixel. The point of moving to WordPress is to use WordPress. Rebuilding Joomla’s exact layout – especially the Module-position-driven layout – in WordPress costs weeks and produces a fragile result. Pick a WordPress theme that works, then adapt your content to it.
  8. Migrating user passwords and assuming they work. Joomla and WordPress hash formats differ. Plan for a forced password reset or a compatibility layer.
  9. Forgetting to rebuild the menu structure manually. Joomla menus and WordPress menus are different concepts. Exporting one and importing the other is not how this works. Recreate each menu in Appearance > Menus.
  10. Cancelling Joomla hosting too early. Wait at least 30 days after the WordPress site is live and stable. Things break, and a backup-restore of the Joomla site can save you.

How long does it take#

Realistic timelines, assuming one or two people working on it and that the source Joomla site is in reasonable shape:

Site typeMigration tool timeRebuild timeTotal elapsed
Brochure site, under 50 articles, core Joomla30 minutes1-2 days2-4 days
Blog, 200-500 articles, standard categories1-2 hours1 week1-2 weeks
K2-driven content site, custom fields2-4 hours (core + K2 plugin)2-3 weeks3-5 weeks
Multilingual core Joomla site, 1,000+ articles4-8 hours, run multiple times3-4 weeks5-8 weeks
VirtueMart or HikaShop store with products and orders4-8 hours for content; commerce data is largely manual4-6 weeks8-12 weeks
Enterprise site with K2 + VirtueMart + custom componentsPlugin gets you to 60%; the rest is bespoke2-4 months3-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 Joomla.” It happens, but it is rare. The path is the same in reverse using a contrib import extension on the Joomla side. Everything else rebuilds. Most people reading this article are going the more common direction, which is what this guide covers.

Summary#

A Joomla to WordPress migration is a real project, not a click. The mechanical content transfer is straightforward with the FG Joomla to WordPress plugin for core Joomla content, plus a K2 companion if you use K2. The rebuild is where the weeks go – Modules, menus, custom fields, multilingual content, and any extension-specific data all have to be redone in WordPress equivalents. Inventory your Joomla site completely before you run any tool, migrate into staging not production, build the redirect map from your SEF aliases so you do not lose SEO, plan for K2 separately if you use it, force password resets on users, and budget realistically for the rebuild. The destination is a larger plugin ecosystem, easier content editing for non-technical users, and a developer pool that is still growing rather than shrinking.