Migrating from XenForo
Forum Pro imports a XenForo 2.2 forum from a plain MySQL dump of its tables plus a copy of two folders from the install. Members keep working passwords, BBCode converts to Markdown, attachments and avatars adopt straight off disk into your own storage, and the import is resumable and idempotent.
What you need
Ask whoever runs the XenForo install for two things:
- A schema-and-data dump of the
xf_*tables. A plainmysqldump xenforo > dump.sqlis right; add--no-tablespaceson shared hosts. phpMyAdmin exports work too. A data-only dump (mysqldump -t) is refused, because without theCREATE TABLEstatements nothing can name the columns. - Two folders from the install:
internal_data/attachmentsanddata/avatars. XenForo gates attachment downloads by permission, so files are read off disk rather than fetched over HTTP.
The dump is stream-parsed in PHP. You do not need MySQL installed on the new server, and a multi-gigabyte dump streams through in constant memory.
The command
bin/plugin forum-pro import-xenforo dump.sql \
--source-url https://forum.example.org \
--xf-root /path/to/xenforo
| Option | Purpose |
|---|---|
--source-url |
The old forum's base URL, including any subfolder such as /community. Internal links in posts are recognized and rewritten from it. |
--xf-root |
The XenForo install root; internal_data/attachments and data/avatars are found under it. |
--attachments-dir, --avatars-dir |
Point at either folder individually, overriding --xf-root. |
--skip-files |
Import the data only. Useful for a first look before the folders arrive. |
--prefixes tag|title|skip |
What to do with thread prefixes: make them tags (the default), prepend [Prefix] to the title, or drop them. |
--skip-pms |
Leave conversations (private messages) behind. |
--default-section |
Section title for forums that have no top-level category above them. |
The dump can be gzipped. A 55 MB dump with 6,000 posts and 2,500 attachments imports in about ten seconds into an empty database.
What comes across
Members and identity
- Members, with working passwords. XenForo 2 stores bcrypt, which Forum Pro verifies natively; accounts still on a XenForo 1 hash verify through a tagged legacy format and upgrade to bcrypt on first login. Usernames with spaces are sanitized into valid handles (
Jane DoebecomesJane_Doe) with the original kept as the display name. - Admins and moderators, as moderator grants. Bans and disabled accounts, as suspensions.
- Custom user groups, with their memberships. XenForo's four stock groups are not created.
- Trophies, as manually awarded badges, and custom titles.
- Signatures and avatars.
Structure and content
- The node tree. A top-level category becomes a section; every forum becomes a category inside the section of its topmost ancestor. Deeper nesting is flattened rather than reproduced, because Forum Pro has exactly two levels. Page and link nodes are skipped. A forum closed to new posts becomes staff-only.
- Threads, with their sticky, open and deleted states and view counts. Redirect threads are skipped.
- Posts, with BBCode converted to Markdown: bold, italic, strikethrough, headings, lists, tables, quotes with attribution, code and inline code, spoilers (as a headed quote, since Forum Pro never renders raw HTML), images,
[USER]mentions,[ATTACH]references and[MEDIA]embeds. Presentation-only tags such as colour, size, font and alignment lose their markup and keep their text. - Edit history, as post revisions.
- Attachments, adopted into content-addressed storage. Images render inline, other files link.
- Reactions, mapped onto your configured types (see below).
- Tags and thread prefixes.
- Accepted answers from question forums.
- Bookmarks, polls with their votes, and thread and forum watches.
- Conversations, as private messages.
Links
- Internal links between threads, posts, forums and members are rewritten to their new addresses, in both the friendly and the
index.php?threads/...form.
Reactions
XenForo ships six reactions (Like, Love, Haha, Wow, Sad, Angry) and Forum Pro ships four (like, heart, laugh, confused). Reaction types are just configuration, so the cleanest move is to configure XenForo's six before you import:
reactions:
enabled: true
types:
like: 1
heart: 1
laugh: 0
wow: 0
sad: 0
angry: 0
emoji:
like: "👍"
heart: "❤️"
laugh: "😄"
wow: "😮"
sad: "😢"
angry: "😡"
The importer matches each XenForo reaction by its title against your reactions.types. A title that names a type keeps its identity, and two synonyms are understood: Love becomes heart and Haha becomes laugh. A reaction you have no type for becomes a like, so nothing is lost even with the default four. Add-on reactions work the same way: name a type after them and they come across as themselves.
Media embeds
[MEDIA] tags become links to the original post, rebuilt from the provider id XenForo stores. YouTube, Vimeo, Twitter/X, Instagram, TikTok, Imgur, Reddit, Facebook, Dailymotion, SoundCloud, Giphy, Flickr, Pinterest and Spotify are recognized. A provider that is not is dropped and counted in the report.
Reading the report
The import ends with a table of counts. Most are inventory; a handful tell you about fidelity:
| Metric | Meaning |
|---|---|
transform regex bailouts |
A post was too much for the BBCode converter, so it kept its raw BBCode rather than lose text. Zero is normal. |
posts transform fallbacks |
A post would have come out empty (it was nothing but tags with no equivalent), so it kept its BBCode. |
attachments missing |
A post referenced a file that was not in the folders you supplied. |
attachments unresolved |
A post referenced an attachment id the dump itself no longer has. Nothing to fix; XenForo had already lost it. |
media unsupported |
An embed from a provider with no known link pattern. |
mentions unresolved |
An @mention of a member who is not in the dump, usually a deleted account. |
passwords dropped |
An account on a password scheme Forum Pro cannot verify, such as an add-on's. Those members use the reset flow once. |
Idempotency
Every imported row carries its XenForo id. Re-running an interrupted import never duplicates anything, and re-running against a fresh dump before cutover only adds what is new.
Behind the scenes the dump is read once into a spool in the system temp directory, keyed on the dump file. A second run of the same file reuses the spool, which is why re-runs are fast.
Mounting at the old address
Most XenForo forums live at their own hostname, often at its root. To keep the address, mount the forum at the site root and let the legacy redirects handle the old URL shapes on the same host:
frontend:
route: ''
legacy_redirects:
enabled: true
xenforo:
hosts: ['forum.example.org']
base_path: ''
target_base: ''
catch_all: false
Make the forum page Grav's home (system.home.alias) as described in Installation. A visitor arriving at /threads/some-title.123/ then lands on the right topic without leaving the host.
If the forum lived in a subfolder, set base_path: '/community'; if the old hostname is going away entirely, catch_all: true sends anything unmapped under that path to the forum index. Unlike the Discourse source, the XenForo one defaults to no catch-all, because the rest of the old host usually keeps working.
| XenForo path | Redirects to |
|---|---|
/threads/<slug>.<id>/ and /threads/<slug>.<id>/post-<n> |
The topic, at the correct post |
/posts/<id>/ |
The post, in its topic |
/forums/<slug>.<id>/ |
The category |
/members/<name>.<id>/ |
The member profile |
/tags/<tag>/ |
The tag |
/index.php?threads/<slug>.<id>/ |
The same, for installs without friendly URLs |
A suggested cutover plan
- Stand the new forum up on a staging host. Configure reactions, groups, spam settings and theming first, because reactions in particular map at import time.
- Get the dump and the two folders and run the import. Read the report.
- Check the result. Open a few BBCode-heavy posts: a release announcement with lists and links, a proposal with a table, a long quoted thread, a post that is mostly attachments. Check a member's avatar, a poll, and a private message.
- Take a fresh dump shortly before cutover and re-run the import to pick up the delta.
- Close the old forum to new posts.
- Point the hostname at the new site with the legacy redirects enabled.
After the import
bin/plugin forum-pro recount # repair denormalized counters
bin/plugin forum-pro reindex # build the search index
bin/plugin forum-pro integrity # read-only consistency report
Things to know
- Custom BBCode from add-ons has no converter, so its tags are stripped and the text kept. If a forum leans on one, tell us which; common ones are quick to add.
- A bare
[word]with no closing tag is kept as text, because changelog-style posts label entries that way and XenForo shows them verbatim. - The metrics ledger does not backfill. The dashboard's activity charts accrue from the day Forum Pro is deployed; totals are correct immediately.
- Links to an even older platform stay as they were. A forum that came to XenForo from somewhere else often still carries that platform's URLs in old posts. Those are not XenForo links, so the importer leaves them alone.