The WordPress WXR Import feature allows administrators to import content from WordPress XML export files directly through the admin interface.
- Log in as an administrator
- Navigate to Admin → System → Import
- Upload a WordPress WXR (.xml) export file
Choose which WordPress post statuses to import:
- Published only (default)
- Published + Drafts
- Published + Drafts + Private
- All statuses (includes pending)
- Dry run: Preview the import without making any changes
- Skip media downloads: Import content without downloading media files
- Purge all data before import:
⚠️ DESTRUCTIVE - Removes all existing posts, comments, categories, tags, redirects, and uploaded files
- Concurrency: Number of simultaneous media downloads (1-10, default: 4)
- Allowed Media Hosts: Whitelist of domains for media downloads (empty = allow all)
- Posts: Title, content, excerpt, publication date, author
- Comments: Content, author info, threading/replies, approval status
- Categories: Names and slugs (hierarchy flattened)
- Tags: Names and slugs
- Media: Images, videos, and other attachments (when S3/R2 configured)
- Users: Authors and commenters (placeholder accounts created)
- Redirects: 301 redirects from old WordPress URLs to new post URLs
- Featured Images: Post thumbnails when
_thumbnail_idmetadata present - URL Rewriting: Internal media URLs updated to new locations
- Upload & Validation: File type and structure validation
- Job Creation: Import job record created with options
- Processing: Content parsed and imported with progress tracking
- Media Downloads: Attachments downloaded to S3/R2 storage
- URL Rewriting: Content URLs updated to new media locations
- Redirect Creation: Old URLs mapped to new post locations
Image Policy: During URL rewriting, remote images are not allowed. Each encountered image is downloaded and served locally. If an image cannot be downloaded (blocked host, network error, unsupported), it is replaced with a local placeholder at
/images/image-cannot-be-downloaded.svg. Protocol-relative (//host/...) URLs are treated as remote.
- Queued: Job created, waiting to start
- Running: Import in progress
- Cancelling: Cancel requested, stopping gracefully
- Cancelled: Import stopped by user
- Failed: Import encountered errors
- Completed: Import finished successfully
- Real-time progress bar during import
- Item counts: total, posts, attachments, redirects, skipped
- Detailed error logging for failed items
- Cancel: Stop a running import
- Retry: Restart a failed or cancelled import
- View Details: See comprehensive job information and errors
- Media Download: Failed to download attachment files
- Post Import: Failed to create or update post records
- Redirect Creation: Failed to create URL redirects
- Fatal Error: Critical system errors
Each error includes:
- Item identifier (GUID, URL, etc.)
- Error message and type
- Relevant item data for debugging
- Timestamp of occurrence
- PostgreSQL database with import job tables
- Required schema:
import_jobs,import_job_errors
For media downloads, configure S3 or Cloudflare R2:
S3_REGION/R2_REGIONS3_ENDPOINT/R2_ENDPOINTS3_ACCESS_KEY_ID/R2_ACCESS_KEY_IDS3_SECRET_ACCESS_KEY/R2_SECRET_ACCESS_KEYS3_BUCKET/R2_BUCKET
- Admin user account required
- File system write access for temporary files
- Only imports posts (skips pages, custom post types)
- Comments imported only for published posts
- WordPress shortcodes preserved as raw HTML
- No WordPress plugin data or custom fields
- Remote images are disallowed in imported post content. Import will either:
- Download and rewrite the image to a local URL, or
- Replace the element with a placeholder image located at
/images/image-cannot-be-downloaded.svgif the download fails.
- Featured images follow the same rule and will only be set when a local copy exists.
- Maximum file size depends on server configuration
- Large imports may require increased timeout limits
- Concurrent media downloads limited to prevent overload
For large imports or automation, use the CLI script:
# Basic import
pnpm wxr:import -- path=./export.xml
# Dry run preview
pnpm wxr:import -- path=./export.xml --dry-run
# Skip media downloads
pnpm wxr:import -- path=./export.xml --skip-media
# Verbose output with concurrency control
pnpm wxr:import -- path=./export.xml --verbose concurrency=8
# Offline import with local media files and complete purge
pnpm wxr:import -- path=./export.xml --purge uploads=/path/to/wp-uploads root='^https?://oldsite\.com$' --verbose
# Import with allowed hosts filter
pnpm wxr:import -- path=./export.xml allowedHosts=example.com,cdn.example.com --verbosepath=<file>: (Required) Path to WXR export file--verbose: Enable detailed logging--dry-run: Preview without making changes--skip-media: Skip media downloads--rebuild-excerpts: Regenerate all excerpts--purge:⚠️ Delete all posts, comments, categories, tags, redirects, and uploaded filesuploads=<path>: Local uploads directory for offline importroot=<pattern>: Regex pattern for old site URL (required with uploads)allowedHosts=<hosts>: Comma-separated allowed domainsconcurrency=<number>: Simultaneous downloads (1-10, default: 4)
- Check file format (must be .xml)
- Verify admin permissions
- Check disk space for temporary files
- Verify S3/R2 configuration
- Check network connectivity to source URLs
- Review allowed hosts whitelist
- Use CLI for very large imports
- Reduce concurrency setting
- Process in smaller batches
- Import during low traffic periods
- Use
--skip-mediafor content-only imports - Monitor server resources during import
- Test First: Always run a dry-run before live import
- Backup: Create database backup before importing
- Media Strategy: Configure S3/R2 before importing media-heavy sites
- Incremental: For large sites, consider importing in smaller batches
- Monitoring: Watch import progress and error logs closely
- Cleanup: Remove temporary files after completed imports