Launched:self-serve migrations intoSuperhuman Docs (Coda)
Try it now
01Agent-first
Runs where you already work
Plug it into Claude, ChatGPT or Cursor. Describe the move in plain English; the agent runs it.
02Engineer-led
Our production engine, unlocked
The pipeline our engineers use on managed enterprise migrations — the same code, now something you can drive yourself.
03Pricing
Try 10 pages free, then $1 a page
Credit-based, pay-as-you-go. No scoping call, no quote — sample it on your own docs before you spend anything.
04Sources
NotionSlabConfluenceSoonGoogle DocsSoon
Skip to content

MediaWiki to Confluence Migration: TWiki, DokuWiki & Legacy Wikis

No native importer exists for MediaWiki, TWiki, or DokuWiki to Confluence. This guide covers the real migration methods, markup conversion, API constraints, and link rewriting.

Abdul Wahab Abdul Wahab · · 22 min read
MediaWiki to Confluence Migration: TWiki, DokuWiki & Legacy Wikis
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

MediaWiki to Confluence Migration: TWiki, DokuWiki & Legacy Wikis

There is no native migration path from MediaWiki, TWiki, or DokuWiki into Confluence. Aside from the no longer supported Universal Wiki Converter, Confluence does not include tools for importing data from specific third-party wikis (support.atlassian.com). Atlassian's own documentation says you may be able to build your own import solution using the REST APIs or work with an Atlassian Solution Partner (confluence.atlassian.com). In practice, that means extracting each page, converting its markup to Confluence storage format, loading it through the REST API, and rewriting internal links in a second pass.

If you're searching for a MediaWiki to Confluence migration tool, a TWiki to Confluence converter, or a way to move DokuWiki pages into Confluence Cloud, you need to understand what actually works — because most guides reference tools that haven't been maintained in over a decade.

This guide covers the real methods: what each legacy wiki exports, how to translate markup into Confluence Storage Format, the two-pass link rewriting strategy that prevents broken internal links, the API constraints that throttle programmatic imports, specific parsers for each source wiki, error handling for common API failures, and where each approach silently drops content.

What does each legacy wiki actually export?

Before picking a migration method, you need to know what your source wiki can give you. The export format determines your entire pipeline.

MediaWiki

MediaWiki's Special:Export produces XML files containing raw wikitext — not HTML, not Confluence markup. Wiki pages can be exported in a special XML format for analysis or upload into another MediaWiki installation. XML dumps contain the content of a wiki (wiki pages with all their revisions), without site-related data — no user accounts, no images, no deleted revisions (mediawiki.org).

Key constraints:

  • The XML wraps raw wikitext markup — you still need a parser to convert [[internal links]], {| table markup |}, templates, and categories
  • A maximum of 100 revisions are returned per export request; large wikis need the dumpBackup.php maintenance script instead (mediawiki.org)
  • Special:Export doesn't provide an automatic way to export all pages at once — you need Special:AllPages to generate the page list first
  • Uploaded images and files are not included in XML exports — they live in the filesystem or database separately

MediaWiki also exposes the Action API, which is often a superior extraction path. The action=parse endpoint forces the MediaWiki server to execute all templates, infoboxes, and transclusions, returning fully rendered HTML, plus lists of the page's categories and templates (mediawiki.org):

curl -G "https://wiki.yourdomain.com/api.php" \
  --data-urlencode "action=parse" \
  --data-urlencode "page=Architecture_Overview" \
  --data-urlencode "format=json"

Comparing action=parse vs. Special:Export output fidelity:

Feature action=parse (HTML output) Special:Export (wikitext XML)
Templates expanded ✅ Fully rendered ❌ Raw {{Template}} calls
Infoboxes ✅ Rendered as HTML tables ❌ Parameter syntax preserved, requires custom parsing
Magic words (__TOC__) ✅ Resolved ❌ Literal text
Categories ✅ Returned as a separate categories list ✅ [[Category:...]] links in the wikitext
Revision history ❌ Not available ✅ Full revision list
Wikitext control ❌ Pre-processed, no access to source ✅ Full source available
Template dependency graph ⚠️ templates list per page ✅ Extractable

The action=parse approach is superior for content fidelity when templates are complex. Special:Export is superior when you need revision history or the template source.

DokuWiki

DokuWiki stores all content as plain .txt files on the filesystem — no database required. All articles are stored as simple text files and all attachments as ordinary files, making extraction trivial: copy the data/pages/ and data/media/ directories.

DokuWiki headers use equals signs, inverted compared to standard conventions:

====== Heading 1 ======
===== Heading 2 =====

Internal links look like this: [[namespace:page|Link Text]]. You can either parse the raw text yourself or let DokuWiki render it: the remote API's core.getPageHTML call and the ?do=export_xhtml page export both return rendered HTML (github.com).

DokuWiki conversion options:

  • Pandoc (-f dokuwiki): Pandoc reads DokuWiki markup natively and can write HTML (pandoc.org). It handles standard syntax such as internal links, headings, and basic formatting, but not third-party plugin syntax.
  • DokuWiki's own renderer: core.getPageHTML or ?do=export_xhtml renders each page with the plugins your instance has installed. This is the most faithful option for plugin-heavy wikis, at the cost of cleaning DokuWiki's HTML afterward.

For DokuWiki plugin syntax (e.g., <note warning> from the Note plugin), no generic parser handles these correctly. Render through DokuWiki itself, write per-plugin regex rules, or accept that plugin content will appear as raw text in Confluence.

TWiki and Foswiki

TWiki stores content in RCS-versioned text files using TWiki Markup Language (TML): each topic is a .txt file in its web's folder under data/, with its history in a ,v file, and attachments live under pub/ (twiki.org). New Foswiki 2.x sites default to a plain-file store that keeps a full copy of each revision instead of RCS files (foswiki.org). Each "web" maps loosely to a Confluence space. TWiki's flexible page structure doesn't map cleanly to Confluence's space-based hierarchy. TML uses a percent-sign macro syntax (%MACRO{}%) that has no Confluence equivalent, and Foswiki/TWiki-specific macros are not successfully interpreted by generic converters — they need custom mapping rules.

A typical TWiki file mixes metadata with content:

%META:TOPICINFO{author="jsmith" date="1610000000" format="1.1" version="1.4"}%
%META:TOPICPARENT{name="EngineeringWeb"}%
---++ Architecture Guidelines
This is the page content.

TWiki TML parsers:

  • TWiki's own renderer: Rendering each topic to HTML through your existing TWiki installation is the most accurate approach — it handles all macros your instance actually uses.
  • Pandoc (-f twiki): Pandoc reads TWiki markup natively (pandoc.org). Expect %MACRO{}% calls to need custom handling.
  • Custom regex pipeline: For wikis with limited TML usage (mostly ---++ headers and bullet lists), a targeted regex script is often faster to write than setting up the reference parser. Map ---++ → <h2>, ---+++ → <h3>, etc., and handle %MACRO{}% calls with an explicit allow-list.

Your extraction script must strip the %META% tags, extract author and date if historical preservation is required, and then convert TML into HTML. TWiki headers use ---++ for H2, ---+++ for H3, and so on.

Why the Universal Wiki Converter no longer works

The Universal Wiki Converter (UWC) was a standalone Java tool that communicated with Confluence's legacy XML-RPC API. Atlassian's documentation says the UWC does not support Confluence versions after 4.3.7 (confluence.atlassian.com).

The problems are stacked:

  1. API incompatibility. The UWC relies on Confluence's XML-RPC remote API, which Atlassian deprecated in Confluence 5.5 (developer.atlassian.com). Modern Confluence integrations use the REST API.
  2. Storage format change. Confluence 4.0 switched from wiki markup to XHTML-based storage format. Atlassian's issue tracker records that the UWC was not compatible with Confluence 4.0 (jira.atlassian.com).
  3. No maintenance. The UWC was an Atlassian Labs app. Its Marketplace listing is archived (marketplace.atlassian.com), and Atlassian lists it as no longer supported.
  4. The workaround is absurd. Community answers suggest importing into a Confluence 4 instance and then upgrading through every major version to reach the current release — meaning you'd stand up decade-old infrastructure just to run a migration. For Confluence Cloud, this path is not viable at all.

If you see a migration guide recommending the UWC, close the tab.

Architecture mismatches: flat vs. hierarchical data models

Confluence requires a strict hierarchy: a Space contains a Root Page, which contains Child Pages. All content must be converted to Confluence Storage Format (CSF), an XML-compliant XHTML derivative. Legacy wikis were built on fundamentally different assumptions, similar to the structural mismatches encountered in a Notion to Confluence migration.

MediaWiki namespaces to Confluence spaces

MediaWiki uses a flat structure organized by Namespaces (e.g., Main, User, Project, Help) and Categories. A page titled Project:Q3_Roadmap exists in the Project namespace.

In Confluence, you must map these namespaces to Spaces. Because MediaWiki lacks a strict parent-child tree, you must programmatically infer hierarchy — typically by parsing subpage syntax (e.g., Parent_Page/Child_Page), analyzing breadcrumbs, or mapping MediaWiki Categories to Confluence parent pages. Pages without an obvious parent land at the root of the Confluence Space and require manual cleanup post-migration.

DokuWiki and TWiki directories to Confluence trees

DokuWiki organizes content in namespaces based on filesystem directories (data/pages/engineering/architecture.txt). TWiki uses "Webs" (directories) containing "Topics" (files).

This filesystem approach translates more cleanly to Confluence. A DokuWiki top-level directory becomes a Confluence Space, nested directories become parent pages, and .txt files become child pages.

Common mapping patterns:

  • One source wiki namespace → one Confluence space
  • One source wiki → one Confluence space, with namespaces becoming top-level page trees
  • Multiple source wikis → one Confluence space (consolidation)

Decide your space structure before migration. Restructuring after import is far more painful.

Confluence Data Center vs. Cloud: key differences

This distinction matters for enterprise readers. The API surface, rate limits, and import tooling differ significantly.

Dimension Confluence Cloud Confluence Data Center
REST API rate limiting Documented points-based quotas for apps; burst limits for API-token scripts; HTTP 429 with Retry-After Admin-configurable rate limiting, on by default from Confluence 11.0; HTTP 429 with Retry-After
HTML Importer ✅ Available ❌ Not available
XML space import ✅ Available ✅ Available
Attachment size limit 100 MB default; admin-configurable 100 MB default; admin-configurable
API authentication API tokens (email + token) Personal access tokens (Bearer) or basic auth
REST API v2 ✅ Available ❌ Not available — use the /rest/api REST API
App ecosystem for migration Wider (Cloud Marketplace) Narrower; some migration apps Cloud-only

Sources for the table: Cloud rate limiting (developer.atlassian.com), Data Center rate limiting (confluence.atlassian.com), and attachment size in Cloud (support.atlassian.com) and Data Center (confluence.atlassian.com).

If you're migrating to Confluence Data Center, skip the HTML Importer entirely and go straight to the Data Center REST API (/rest/api/content). Ask your admin how rate limiting is configured, and use exponential backoff to avoid overwhelming the server during large imports.

Migration methods that actually work

Method Source Wikis Fidelity Attachments Hierarchy Link Rewriting Scale
Manual copy-paste Any Low–Medium Manual re-upload Manual ❌ <50 pages
Confluence HTML Importer Any (via HTML export) Medium Images only ❌ Flat ❌ <500 pages
Pandoc + REST API pipeline MediaWiki, DokuWiki, TWiki Medium–High Separate script Custom Custom 500–10,000+ pages
WikiLumper DokuWiki, XWiki Medium ✅ ✅ Partial <2,000 pages
ClonePartner managed migration Any legacy wiki High ✅ ✅ ✅ Any scale

Manual copy-paste (small wikis only)

For wikis with fewer than 50 pages, copy-paste from the rendered wiki view into the Confluence editor is surprisingly effective. Copy from viewing mode, not edit mode, or you'll get raw wikitext. Every page is a manual job, so at 500 pages it's impractical.

What breaks:

  • Internal wiki links paste as dead links pointing at the old wiki
  • Templates and infoboxes don't survive at all
  • Tables with complex spans often need manual fixing
  • Attachments and images must be re-uploaded individually
  • Articles in Confluence will be owned by whoever transfers them — original authorship is lost

Confluence Cloud HTML Importer

You access it via Spaces → Import from other tools → HTML, uploading a ZIP of .html files, and it creates a new space (support.atlassian.com). The pipeline: export your wiki as HTML (the action=parse API or a web scraper — MediaWiki's DumpHTML extension is archived and no longer supports recent MediaWiki releases, per mediawiki.org), package as a ZIP, upload to Confluence.

The ZIP holds one folder of .html files. Each file becomes a page, and its images sit in a folder named after the page. Headings, lists, tables, links and images come across. Code blocks arrive as plain text, custom text colors are lost, and unsupported media is ignored (support.atlassian.com). We detail similar limitations in our Document360 to Confluence migration guide.

Limitations:

  • The documented ZIP layout is a single folder of pages, so expect a flat page list. Only XML space import preserves an existing Confluence page tree. Teams are often disappointed when a bulk import succeeds but the destination architecture is wrong — all pages land flat and need manual restructuring.
  • Unsupported media is ignored, so plan to upload PDFs and Office documents separately
  • A link to another page becomes a plain hyperlink, not a Confluence page link
  • No macro translation — anything that was a wiki template renders as static HTML or vanishes
  • Cloud only — not available in Confluence Data Center

This method works for archiving text-heavy content where restructuring is acceptable. It's not a migration — it's a dump.

How to build a Pandoc + REST API migration pipeline

This is the method that produces the best results for engineering teams willing to write scripts. The pipeline has four stages: extract, convert, import, relink.

Stage 1: Extract content from the source wiki.

For MediaWiki, you have two extraction paths. The Action API action=parse endpoint is the stronger engineering approach — it returns fully rendered HTML with all templates expanded:

# Fetch all page titles
curl "https://wiki.example.com/api.php?action=query&list=allpages&aplimit=500&format=json"
 
# Fetch pre-rendered HTML for a single page
curl -G "https://wiki.example.com/api.php" \
  --data-urlencode "action=parse" \
  --data-urlencode "page=Architecture_Overview" \
  --data-urlencode "format=json"

The alternative is Special:Export for raw wikitext, which gives you more control over template handling and revision history but means you must resolve all templates yourself.

For DokuWiki, copy the data/pages/ directory tree directly. For TWiki, copy the data/ directory containing the .txt topic files (stripping %META% tags during processing) and the pub/ directory that holds attachments.

Stage 2: Convert markup.

Pandoc is a document conversion tool (implemented in Haskell) that supports MediaWiki markup as a native input format (-f mediawiki) and outputs HTML, among many other formats.

# MediaWiki wikitext → HTML (suitable for Confluence storage format)
pandoc -f mediawiki -t html -o output.html input.wiki

Pandoc also reads DokuWiki (-f dokuwiki) and TWiki (-f twiki) markup (pandoc.org). Plugin syntax and TWiki macros still need custom rules, or rendering through the source wiki itself. Test every conversion path against representative samples.

Because Pandoc's intermediate representation of a document is less expressive than many of the formats it converts between, conversions are not perfect. Pandoc attempts to preserve structural elements but not formatting details. Complex tables may not survive conversion.

What Pandoc handles well: headings, bold/italic, bullet lists, numbered lists, simple tables, basic internal links.

What Pandoc drops or mangles: nested tables, MediaWiki templates (especially infoboxes), category tags, magic words (__TOC__, __NOTOC__), DokuWiki plugin syntax, TWiki macros.

If you used the action=parse approach in Stage 1 (getting pre-rendered HTML instead of raw wikitext), you can skip Pandoc entirely and go straight to cleaning the HTML output into valid Confluence Storage Format with a DOM parser such as BeautifulSoup (Python) or Cheerio (Node.js).

Stage 3: Push to Confluence via REST API.

Confluence Storage Format (CSF) is strictly validated XML. The Confluence REST API v2 accepts XHTML storage format. A minimal page creation call:

import requests
 
base_url = "https://yoursite.atlassian.net/wiki"
headers = {
    "Authorization": "Basic <base64_email:api_token>",
    "Content-Type": "application/json"
}
 
payload = {
    "spaceId": "<space_id>",
    "title": "Architecture Guidelines",
    "parentId": "<parent_page_id>",
    "status": "current",
    "body": {
        "representation": "storage",
        "value": "<h2>Architecture Guidelines</h2><p>This is the page content.</p>"
    }
}
 
response = requests.post(
    f"{base_url}/api/v2/pages",
    json=payload,
    headers=headers
)

Attachments require a separate call per file per page. The v2 API can list attachments but has no upload endpoint (developer.atlassian.com), so uploads go through the v1 content API, which requires the X-Atlassian-Token: nocheck header:

curl -X POST \
  -H "Authorization: Basic <credentials>" \
  -H "X-Atlassian-Token: nocheck" \
  -F "file=@image.png" \
  "https://yoursite.atlassian.net/wiki/rest/api/content/{page_id}/child/attachment"

Stage 4: Rewrite internal links (two-pass strategy).

This is covered in detail in the next section — it requires all pages to exist before links can be resolved.

WikiLumper for DokuWiki migrations

WikiLumper is a Perl-based tool for migration from DokuWiki and XWiki to Atlassian Confluence. It reads DokuWiki's filesystem directly and writes to Confluence via the REST API. It can copy all articles, copy all attachments, translate markup (at best effort), and preserve page hierarchy (github.com).

What WikiLumper cannot do: preserve authors or page history. It's a useful starting point for DokuWiki instances with mostly text content.

WikiLumper maintenance status: The last commit was in January 2025, and an open issue asks about Confluence version compatibility. Test it against your specific Confluence version before committing to it as your primary migration tool — REST API changes may cause failures that aren't immediately obvious.

What breaks in every legacy wiki migration to Confluence

Regardless of method, certain content categories require special handling or will be lost.

Templates and transclusion

MediaWiki templates ({{Template:Name}}) are the single hardest content type to migrate. A template call in MediaWiki is server-side transclusion — the template is rendered at view time with parameter substitution. Confluence has no equivalent mechanism.

Your options:

  1. Pre-render — use the action=parse API to export fully rendered HTML (with templates already expanded). This preserves the visual output but loses the template relationship.
  2. Map to Confluence macros — simple transclusions can be replaced with the Confluence Include Page macro:
<ac:structured-macro ac:name="include">
  <ac:parameter ac:name="">
    <ac:link>
      <ri:page ri:content-title="Template_Name" />
    </ac:link>
  </ac:parameter>
</ac:structured-macro>
  1. Flatten to static HTML — the most common approach for complex templates.
Warning

MediaWiki templates often accept positional or named parameters (e.g., {{Infobox | name=Server1 | ip=10.0.0.5}}). Confluence's Include Page macro does not support passing parameters. Complex infoboxes must be programmatically flattened into static HTML tables during migration, or they will break.

Confluence page templates are fundamentally different from MediaWiki templates — they're blueprints for creating new pages, not reusable content blocks. Don't confuse the two.

MediaWiki uses [[Page Name]] syntax. DokuWiki uses [[namespace:page]] with colon separators. TWiki uses [[Web.TopicName]]. None of these map directly to Confluence's internal link format. In storage format, a page link names the target page's title, plus its space key when it points to another space (confluence.atlassian.com).

Legacy link targets rarely match the final Confluence titles: titles get cleaned up, de-duplicated, or land in a different space during import. You only know each page's final title, space and Page ID once it has been created. That requires a two-pass migration strategy (the same approach required for Quip to Confluence migrations).

Pass 1: Content Ingestion and ID Mapping

  1. Strip all internal links from the source text and replace them with a custom placeholder (e.g., {{LINK:Architecture_Guidelines}}).
  2. Push the page to Confluence via the API.
  3. Capture the HTTP 200 response, extract the newly generated Confluence Page ID and final title, and store the mapping (e.g., Source_Title: Architecture_Guidelines → Confluence_ID: 987654, Title: Architecture Guidelines).

Pass 2: Link Rewriting

  1. Iterate through your newly created Confluence pages.
  2. Search the page body for your placeholders.
  3. Look up the corresponding Confluence page (ID, final title and space) in your mapping table.
  4. Replace the placeholder with the correct Confluence link macro:
<ac:link>
  <ri:page ri:content-title="Architecture Guidelines" />
</ac:link>
  1. Issue a PUT request to update the Confluence page with the rewritten links.

If you attempt to do this in a single pass, pages that link to content further down the migration queue will fail to resolve. Miss the second pass entirely and your entire wiki is full of dead links.

Handling broken source links: Some source wiki pages will contain links to pages that no longer exist, were never migrated, or used non-standard title formats. During Pass 2, any placeholder that has no corresponding entry in your mapping table is an orphaned link. Log these to a CSV (orphaned_links.csv) with the containing page title, placeholder text, and original link target. This becomes your post-migration cleanup list.

For more on link rewriting across platforms, see our post on migrating images, attachments & embeds without broken links.

Images and file attachments

Images and files live outside the wiki markup in all three source systems. They must be downloaded separately (from the filesystem, database, or API), then uploaded as Confluence attachments via the REST API, then the page body references must be updated to point at the Confluence attachment URL.

Attachments cannot be uploaded in the same API call as page creation — you must first POST the page content, retrieve the Page ID, then issue a multipart/form-data POST to the attachments endpoint.

The default maximum attachment size is 100 MB in both Confluence Cloud and Data Center, and admins can change it (support.atlassian.com). If your legacy wiki contains database dumps, ISOs, or large media files exceeding the applicable limit, the API upload will fail — the v1 attachment API documents an HTTP 404 for an attachment over the configured maximum. These files must be identified during extraction, hosted externally (e.g., AWS S3 or SharePoint), with a standard HTML link placed on the Confluence page.

API error handling: common failure modes

A production migration script must handle more than HTTP 429. These are the most common failure modes and their causes:

HTTP 400 — Malformed Confluence Storage Format

This is the most common error in programmatic migrations (and a frequent hurdle when migrating Zendesk to Confluence). Confluence Storage Format is strictly validated XHTML. Any of the following will trigger a 400:

  • Unclosed HTML tags (e.g., <br> instead of <br/>)
  • Unescaped ampersands in URLs or text (& must be &amp;)
  • Invalid attribute values in Confluence macros
  • Non-UTF-8 characters from legacy wiki encodings (common in older MediaWiki or TWiki installations using Latin-1)
  • Nested block elements that XHTML prohibits (e.g., <p> inside <p>)

Fix: Run your converted HTML through an XML validator (Python's lxml.etree.fromstring() or xmllint --noout) before submitting to the API. Log the validation error with the page title and the offending fragment. Fix programmatically where possible (e.g., ampersand escaping), flag for manual review where not.

from lxml import etree
 
def validate_csf(html_content):
    try:
        # Wrap in a root element as CSF is an XML fragment
        etree.fromstring(f"<root>{html_content}</root>")
        return True, None
    except etree.XMLSyntaxError as e:
        return False, str(e)

Attachment Too Large

The attachment exceeds the configured maximum, and the upload fails. Log the filename, size, and containing page. Host externally and replace the attachment reference with an HTML link.

HTTP 429 — Rate Limited

Confluence Cloud returns a Retry-After header (in seconds) with HTTP 429 responses. Your migration script must respect this header. Implement exponential backoff with jitter:

import time
import random
 
def post_with_retry(session, url, payload, max_retries=5):
    for attempt in range(max_retries):
        response = session.post(url, json=payload)
        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 60))
            jitter = random.uniform(0, retry_after * 0.1)
            time.sleep(retry_after + jitter)
            continue
        elif response.status_code == 400:
            # Log and skip — retrying won't fix malformed content
            log_error(url, payload, response.text)
            return None
        response.raise_for_status()
        return response
    raise Exception(f"Max retries exceeded for {url}")

HTTP 404 — Parent Page Not Found

Occurs when you specify a parentId that doesn't exist — typically because the parent page failed to import earlier in the queue. Implement dependency ordering: sort pages so parents are always imported before children. For pages whose parent import failed, fall back to the Space root rather than dropping the page.

HTTP 403 — Permission Error

Your API token lacks permission to create pages in the target space. Verify that the account associated with the API token has Space Admin or Create Pages permission on the target space before beginning migration.

Encoding errors (silent data corruption)

Older MediaWiki and TWiki installations may use Latin-1 or Windows-1252 encoding. When you read these files as UTF-8, characters above code point 127 silently corrupt. Always detect encoding before reading:

import chardet
 
with open(filepath, "rb") as f:
    raw = f.read()
    detected = chardet.detect(raw)
    encoding = detected["encoding"] or "utf-8"
    content = raw.decode(encoding)

What are Confluence's API rate limits for migration?

Confluence Cloud measures app traffic with a points-based model: each request costs a base point plus points per object involved, against hourly quotas that Atlassian documents. API-token traffic, which most migration scripts use, is governed by burst rate limits instead. Either way, an over-limit request gets HTTP 429 with a Retry-After header (developer.atlassian.com).

Rate limiting is amplified by the N+1 request pattern inherent in Confluence's API — creating one page requires a POST for the page, then separate POSTs for each attachment, label, and property. Start with low concurrency, watch for 429s, and raise it only while responses stay clean.

For Confluence Data Center, rate limiting is admin-configurable and on by default from Confluence 11.0. Throughput is also bounded by server hardware. Test at increasing concurrency and monitor server load.

For a deep dive on Confluence import methods and limits, see our import guide.

What about version history?

You almost certainly won't preserve it. MediaWiki's Special:Export can include revision history, but Confluence's REST API creates pages with a single initial version. Importing historical versions would require creating each revision as a sequential page update — which means one API call per revision per page. For a wiki with 1,000 pages averaging 20 revisions each, that's 20,000 API calls for history alone, before any content, attachments, or link rewriting.

If audit trails matter, archive the source wiki in read-only mode alongside Confluence. For more on this trade-off, see our guide on preserving version history in knowledge base migrations.

Migration validation strategy

"Validate" is not an action item — it's a process. A complete validation after import consists of four checks:

1. Record count parity

# Count pages in Confluence space after migration
import requests
 
def count_confluence_pages(space_id, base_url, auth):
    # base_url: https://yoursite.atlassian.net/wiki
    site = base_url.rsplit("/wiki", 1)[0]
    url = f"{base_url}/api/v2/spaces/{space_id}/pages?limit=250"
    total = 0
    while url:
        data = requests.get(url, auth=auth).json()
        total += len(data["results"])
        # _links.next is a relative URL that carries the cursor
        next_link = data.get("_links", {}).get("next")
        url = f"{site}{next_link}" if next_link else None
    return total

Compare this count against your source wiki page count. A discrepancy indicates pages that failed to import — cross-reference against your error log to identify which ones.

2. Orphaned link scan

After Pass 2 of link rewriting, search all Confluence page bodies for any remaining {{LINK: placeholders. These indicate links whose source titles had no match in your mapping table — either pages that were skipped, failed to import, or had title normalization mismatches.

# If you exported page bodies to a local directory for validation
grep -r "{{LINK:" ./confluence_export/ > orphaned_links.txt

3. Attachment reference audit

For each page that should have attachments, verify the attachment count in Confluence matches the source. The Confluence API returns attachment metadata at /api/v2/pages/{page_id}/attachments.

4. Rendering spot-check on a stratified sample

Select 20–30 pages that represent the full complexity distribution of your wiki: pages with simple text, pages with tables, pages with templates, pages with attachments, and pages with many internal links. Load each in a browser and visually verify against the source wiki. Focus on: table structure, image rendering, internal link targets, and formatting that the API accepted but may render incorrectly.

Decision guide: which method for which wiki

Under 50 pages, any source wiki: Copy-paste from the rendered view. Accept that original authorship will be lost.

50–500 pages, mostly text, MediaWiki: Export rendered HTML with action=parse, use Confluence's HTML Importer (Cloud only), then manually restructure the page tree and re-upload attachments. Accept formatting loss on templates and plugin-rendered content.

500–5,000 pages, MediaWiki: Build a Pandoc + REST API pipeline using action=parse for template-heavy content. Budget engineering time for link rewriting, attachment handling, and XML validation. Test on a representative sample of 20–50 pages before the full run.

DokuWiki, any size: Use Pandoc's DokuWiki reader, or DokuWiki's own HTML export for plugin-heavy pages, for markup conversion. Start with WikiLumper for a baseline migration if your content is mostly text with standard syntax, then handle attachment cleanup and link rewriting separately. For instances with heavy plugin usage, go straight to a custom API pipeline.

TWiki or Foswiki: No open-source converter covers your instance's TML macros. Render through your own TWiki, or use Pandoc's TWiki reader with custom macro rules, then push to Confluence via REST API. This is a significant engineering project, and macro complexity drives the effort.

Any wiki, complex content, tight deadline: Template mapping, link rewriting, attachment handling, error recovery, and validation across thousands of pages is exactly the kind of work where experience saves weeks of debugging. Consider a migration partner.

Tip

Before starting any migration, audit your source wiki. Most legacy wikis have significant content rot — orphaned pages, outdated drafts, duplicate content. Export only what your team has accessed in the last 12 months. Migration is the best time to prune.

Pre-migration checklist

  1. Inventory your content. Count pages, namespaces, templates, and attachments. Identify which pages have been accessed in the last 12 months.
  2. Map your information architecture. Decide which wiki namespaces/webs map to which Confluence spaces. Define the page tree structure before migration.
  3. Identify custom content types. List every template, macro, plugin, and extension your wiki uses. For each, decide: convert to a Confluence macro, pre-render to static HTML, or drop.
  4. Identify encoding. Detect character encoding on source files using chardet or equivalent. Normalize to UTF-8 before processing.
  5. Export and validate a sample. Run your chosen method on 20–50 pages that represent the full complexity of your wiki. Check formatting, links, images, and tables. Validate output HTML as well-formed XML before submitting to the API.
  6. Build your link mapping table. Create a CSV of old page titles → new Confluence page IDs. This is the foundation of link rewriting.
  7. Run the full migration. Import all content, upload all attachments. Log all HTTP errors with page title and error body.
  8. Rewrite internal links. Execute Pass 2 to replace placeholders with Confluence link macros. Log unresolved placeholders to orphaned_links.csv.
  9. Validate. Record-count parity, orphaned link scan, attachment reference audit, rendering spot-check on a stratified sample.
  10. Set the source wiki to read-only. Keep it accessible for reference during the transition period. Decommission after the team has fully adopted Confluence.

Making the right call

Legacy wiki to Confluence migrations are unglamorous work. The markup translation is lossy, the tooling is abandoned or half-maintained, and the edge cases multiply with every template, plugin, and custom extension your wiki accumulated over the years.

The teams that succeed audit ruthlessly (migrating only the content people still use), test on representative samples before committing, validate systematically after import, and budget time for post-migration cleanup. The teams that struggle expect a one-click converter to exist and discover that it doesn't around hour eight of debugging a Pandoc pipeline on a Thursday night.

If your wiki has fewer than a few hundred mostly-text pages, a Pandoc pipeline or WikiLumper will get you there. If you're looking at thousands of pages with complex templates, TWiki macros, or DokuWiki plugin syntax — and you need it done in days, not months — that's what we built ClonePartner to handle.

At ClonePartner, we handle the entire extraction, markup conversion, link rewriting, and validation process. We operate on a fixed-price model per project, starting at $500. We connect to your source wiki, run sample migrations until the data mapping is validated, then run the bulk load during the working days before go-live while your team keeps working in the old wiki. On go-live Monday morning, the legacy wiki goes read-only before the working day starts, a final delta of changed pages runs (about 30 minutes), and your team opens Confluence that Monday. The data migration we perform usually completes within 1–5 business days depending on data volume, markup complexity, and API rate limits. Your own space design and Confluence rollout are a separate project on your timeline.

Frequently Asked Questions

Is there a native MediaWiki to Confluence migration tool?
No. Confluence has no built-in importer for MediaWiki. The Universal Wiki Converter (UWC), an archived Atlassian Labs app, is no longer supported and does not support Confluence versions after 4.3.7. For current Confluence (Cloud or Data Center), you need either Confluence Cloud's HTML importer, a custom Pandoc + REST API pipeline, or a migration service.
How do I migrate DokuWiki to Confluence?
DokuWiki stores pages as plain text files, making extraction easy. WikiLumper is an open-source Perl tool that can copy articles, attachments, and page hierarchy from DokuWiki to Confluence via the REST API. For larger or more complex instances, build a custom pipeline that converts DokuWiki markup to HTML (Pandoc reads DokuWiki markup natively) and imports pages through the Confluence REST API.
How do you migrate MediaWiki templates to Confluence?
Simple templates can be mapped to Confluence's Include Page macro. However, complex templates with parameters (like infoboxes) must be programmatically flattened into static HTML tables during the extraction phase, as Confluence does not support parameterized page inclusions. The most reliable approach is to use MediaWiki's action=parse API to export pre-rendered HTML with all templates already expanded.
Will internal wiki links break when moving to Confluence?
They will break unless a two-pass migration strategy is used. Pages must first be created so you know each page's final Confluence title, space and ID, and then a second script must rewrite the source links into Confluence link markup that points at those pages.
How long does a legacy wiki to Confluence migration take?
The data migration ClonePartner performs typically completes within 1–5 business days, depending on data volume, complexity, and API rate limits. Small wikis can finish in under 24 hours. This does not include your team's time for content audit, page tree restructuring, template-to-macro mapping decisions, and post-migration cleanup.

More from our Blog

The Ultimate Guide: Migrating from Notion to Confluence (Technical & Strategic)
Notion/Confluence/Migration Guide

The Ultimate Guide: Migrating from Notion to Confluence (Technical & Strategic)

A practical guide to migrating Notion to Confluence that explains how Notion blocks map to Confluence pages and macros, highlights common migration failures such as flattened databases and broken relations, and outlines when to use native export, custom API scripts, or automated migration pipelines. The guide helps teams preserve structured data, maintain documentation integrity, and plan a reliable transition to Confluence.

Raajshekhar Rajan Raajshekhar Rajan · · 10 min read