How to Migrate from Substack to Ghost
Move your Substack publication to Ghost without losing subscribers. Step-by-step guide covering content, paid members, Stripe, and what to watch for.
Why Publishers Leave Substack
Substack takes 10% of your subscription revenue plus Stripe fees. On Ghost, the platform fee is 0%.
At $5,000/month in revenue, Substack takes $500 every month. On Ghost, that $500 stays in your account. Over a year, that is $6,000 in savings. It would cover Ghost(Pro) Publisher for over 17 years.
The fee is not the only reason people move. Substack’s design is the same for every publication. Its SEO controls are minimal. And on Ghost, your subscribers live on your platform, on your terms.
This guide covers each step of moving from Substack to Ghost: your content, your subscribers, and, most importantly, your paid memberships. It also covers the errors people most often hit along the way, and what to do after the move.
What Transfers
Ghost has official Substack migration support. The import tool handles:
| Content | Transfers? | Notes |
|---|---|---|
| Posts | Yes | All published and draft posts |
| Images | Yes | Inline images from posts |
| Free subscribers | Yes | Email addresses and names |
| Paid subscribers | Yes | Via shared Stripe account (see below) |
| Post dates | Yes | Original publication dates preserved |
| Post URLs | Yes | Slugs preserved to maintain links |
What Does Not Transfer
| Content | Why Not |
|---|---|
| Substack Notes | Notes are Substack-specific social features with no Ghost equivalent |
| Substack Chat | Chat history stays on Substack |
| Subscriber activity data | Open rates, click history from Substack are not exported |
| Recommendation lists | Your Substack recommendation network does not migrate |
| Custom subdomain | Your .substack.com URL stays with Substack |
| Profile customizations | Bio, avatar, and profile settings need to be recreated |
| Apple in-app subscribers | Readers who subscribed through the Substack iOS app pay Apple, not your Stripe account — there is no Stripe customer to migrate (see troubleshooting below) |
The Stripe Connection: Key to Paid Migration
Both Substack and Ghost take payments through Stripe. Because they share that layer, paid subscribers can move across without re-subscribing. Handling your Stripe account correctly is the most important part of this migration.
How It Works
- Substack connected to your Stripe account when you set up paid subscriptions
- Ghost connects to the same Stripe account
- Ghost matches Substack subscribers to their Stripe customer IDs
- Existing subscriptions continue billing through Ghost instead of Substack
The Critical Step: Disconnect Substack from Stripe
After connecting Ghost to your Stripe account, you must disconnect Substack. If you do not:
- Substack continues receiving its 10% fee on existing subscriptions
- You may have two platforms trying to manage the same Stripe subscriptions
- Subscribers could be double-billed
Contact Substack support to request disconnection from your Stripe account. This is not self-service. You need Substack to disconnect on their end.
Statement Descriptor
The statement descriptor is the name subscribers see next to the charge on their credit card statements. After migration, check it in your Stripe public details settings. It might still say “Substack” from the original setup. Update it to your publication name so subscribers see the correct name.
Step-by-Step Migration
Step 1: Set Up Ghost
Before migrating, have your Ghost site ready:
- Sign up for Ghost(Pro) Publisher ($29/month) or set up a self-hosted instance
- Choose and install your Ghost theme
- Configure basic settings (site title, description, navigation)
- Connect your Stripe account to Ghost (Settings → Membership → Connect to Stripe)
Use the same Stripe account that is connected to your Substack. This is essential for paid subscriber continuity.
Step 2: Export From Substack
- In Substack, go to Settings → Export Data
- Download your content export (posts and subscriber data)
- Also download your subscriber CSV from the Subscribers tab
Note: Substack’s CSV exports can be inconsistent. Some exports are missing Stripe customer IDs for paid subscribers. Ghost’s import tool handles this by matching subscribers through the shared Stripe account. Even so, verify your paid subscriber count after import.
Step 3: Import Into Ghost
- In Ghost Admin, go to Settings → Advanced → Import/Export
- Upload your Substack export zip — Ghost detects it and runs the Substack importer
- Import your free and paid subscriber CSVs separately via Members → Import
- When importing subscribers, apply a label such as
substack-import. You will need it later for the welcome email (see troubleshooting)
Ghost’s Substack importer is built for this job. It converts posts, preserves dates and slugs, and matches paid subscribers to Stripe. Two ordering rules matter, and many failed migrations come down to one of them. Connect Stripe before importing paid subscribers, and create your paid tiers before the import too. Otherwise Ghost cannot match subscriptions and skips those members.
Step 4: Verify Content
After import, check:
- Open five to ten posts and verify content, images, and formatting
- Verify post dates are correct
- Check that post slugs match your Substack URLs (they should)
- Confirm all images load properly
Step 5: Verify Subscribers
In Ghost Admin, check the Members section:
- Total members: Should match your Substack subscriber count
- Paid members: Should match your Substack paid subscriber count
- Stripe connection: Verify paid members show correct Stripe subscription status
If paid subscriber counts do not match, check your Stripe Dashboard for subscriptions that may not have been matched. Ghost support can help resolve discrepancies.
Step 6: Set Up Your Newsletter
Configure your Ghost newsletter settings:
- Go to Settings → Newsletters
- Set your sender name and email
- Configure email design (header image, fonts, colors)
- On Publisher plan: set up a custom sending domain
Step 7: Disconnect Substack from Stripe
This is the step you cannot skip:
- Contact Substack support requesting disconnection from your Stripe account
- Verify in your Stripe Dashboard that Substack’s application is no longer connected
- Confirm Ghost is the only platform connected to your Stripe subscriptions
Step 8: Redirect Your Domain
If you were using a custom domain on Substack:
- Update DNS to point to your Ghost site
- Remove the domain from Substack’s settings
- Add the
/p/redirect rule so old Substack links keep working (next section)
If you were on a .substack.com URL:
- There is no way to redirect from your Substack URL
- Publish a final post on Substack pointing readers to your new Ghost URL
- Consider keeping the Substack profile page active with a link to your new site
Step 9: Notify Your Subscribers
Send a newsletter through Ghost to all subscribers announcing the move:
- Explain what changed (new platform, same content)
- Note that their subscription is unaffected (billing continues normally)
- Highlight any new features (archive on your domain, improved design)
- Ask them to update any bookmarks to your new URL
Troubleshooting: The Errors Migrators Hit Most Often
These are the problems that come up most often in Substack-to-Ghost migrations, with the fixes that resolve them.
”File Type Not Allowed” When Uploading the Export
You upload the zip straight from Substack and Ghost rejects it with “File Type Not Allowed”. The export is not broken. This is a Windows quirk. Every file carries a type label, called a MIME type, that tells software what kind of file it is. Windows labels zip files as application/x-zip-compressed, while Ghost’s importer expects application/zip, so a valid export gets bounced.
Fixes, in order of effort:
- Unzip and re-zip the export, then upload again. Repacking often normalizes the file type.
- Upload from a different OS. The same zip that fails on Windows imports cleanly from macOS or Linux.
”Could not find Stripe customer” on Paid Subscriber Import
Your paid CSV import fails member by member with “Could not find Stripe customer”. Each row of your CSV carries a Stripe customer ID (stripe_customer_id). Ghost looks that ID up in the Stripe account it is connected to, and it is not finding it. The usual causes:
- Ghost is connected to a different Stripe account than the one Substack billed through. This is easy to do if Stripe has split your business into multiple accounts. Check which account holds the subscriptions before connecting.
- Wrong mode. Stripe has a test mode and a live mode. Ghost is connected in test mode while the customers live in live mode.
- Missing tiers: Ghost needs your paid tiers created before the import, or it cannot match subscriptions to a product.
- Substack was disconnected from Stripe too early. If Substack disconnects mid-migration, you can lose every imported paid member. Import first, verify counts, then have Substack disconnect.
The order that works: same Stripe account → live mode → tiers created → import paid CSV → verify → disconnect Substack.
Old /p/ Links Break Without a Redirect
Substack serves posts at yourdomain.com/p/post-slug. Ghost serves them at yourdomain.com/post-slug. On a custom domain, every old link, search result, and social share hits a 404 until you add a redirect. Ghost manages redirects through a file called redirects.yaml, which you upload under Settings → Labs. This is Ghost’s official rule for Substack:
301: \/p\/(?![0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})(.*): /$1The long middle part matters. Ghost’s own editor previews live at /p/<uuid>, so a simpler /p/(.*) rule breaks post previews in Ghost Admin. Many people hit that before the official rule added the UUID exclusion. Use the rule as written.
On a .substack.com address there is nothing to redirect, because you never controlled that domain. Publish a final Substack post pointing to your new site instead.
Images Still Hosted on Substack’s CDN
Substack serves its images from a content delivery network, or CDN, at substackcdn.com. Open a migrated post and inspect an image. If the URL points there, your “migrated” images still live on Substack’s servers. It works today, but your content now depends on a platform you just left. If that account or CDN path ever goes away, your archive loses its images.
The fix depends on where you are in the migration:
- Before/during migration: use Ghost’s open-source migrate CLI. Running
migrate substackwith--scrape all(or--scrape assets) downloads images into the import zip so they upload to your own site - Already imported: there is no one-click re-host. The usual approach is a script against the Ghost Admin API: find Substack image URLs in post HTML, download each image, upload it via the API, and rewrite the post. Ghost(Pro) customers can ask Ghost’s migrations team for help instead.
Either way, verify by spot-checking image URLs. They should start with your domain and /content/images/.
Welcome Emails Don’t Fire for Imported Members
Ghost’s welcome emails and welcome-flow automations trigger on signup, meaning someone typing their address into your site. Members who arrive via CSV import get nothing. This catches many migrators out: your entire migrated audience silently skips your onboarding.
The workaround is the label from Step 3: filter Members by your substack-import label and send a one-off welcome post or email to exactly that group. It doubles as your migration announcement.
Apple In-App Subscribers Cannot Be Migrated
Since Substack adopted Apple’s in-app purchase system for iOS subscriptions in 2025, readers who subscribed inside the iPhone app pay Apple. Their billing never touches your Stripe account. With no Stripe customer record, Ghost has nothing to match, and no migration path exists.
What you can do: export their emails, import them as free members, and run a re-subscribe campaign with a discount offer for former paid readers. Expect to lose some. This is a strong argument for migrating before your iOS-subscriber share grows.
Substack Content Formatting Issues
Substack’s content format is simpler than Ghost’s. Some formatting may not convert perfectly:
- Buttons: Substack subscribe buttons become text links
- Embeds: Some third-party embeds may need to be re-added
- Image captions: May need reformatting
Ghost’s editor builds posts out of blocks it calls cards. Once you know your way around them, these fixes are quick. Our Ghost editor guide walks through buttons, embeds, and captions.
Email Deliverability After Migration
Your first few Ghost sends may have lower deliverability while email providers learn your new sending setup. To improve it:
- Set up the email authentication records (SPF, DKIM, and DMARC) for your custom sending domain
- Start with your most engaged subscribers
- Monitor open rates and check for spam folder placement
- Gradually increase send volume
After Migration
Set Up SEO
Your Substack posts had minimal SEO optimization. Now on Ghost, you can:
- Add custom meta titles and descriptions to your most important posts
- Verify your sitemap at
yourdomain.com/sitemap.xml - Submit your sitemap to Google Search Console
- Set up proper canonical URLs
Every post is now a permanent, indexable web page on your domain. That builds search traffic Substack never provided.
The Revenue Math
Calculate your annual savings:
| Monthly Revenue | Substack Fee (10%) | Ghost(Pro) Publisher | Annual Savings |
|---|---|---|---|
| $1,000 | $100/mo | $29/mo | $852/year |
| $3,000 | $300/mo | $29/mo | $3,252/year |
| $5,000 | $500/mo | $63/mo | $5,244/year |
| $10,000 | $1,000/mo | $88/mo | $10,944/year |
The savings grow with your revenue. Because Ghost’s pricing is fixed, growing does not raise your platform fees.
Your New Publication Identity
The most visible change after migration is design. Every Substack looks the same. Your Ghost publication looks like yours.
If you want your publication to look like your own after the move, our themes include dark mode, multilingual translations, and membership pages, starting at $69.
See the best Ghost themes for newsletters →
That is the whole move: your content, subscribers, and paid memberships are on Ghost, and Substack is disconnected from Stripe. Day one after migrating is picking your look. The best Ghost themes guide is a fast way to choose.
If you are still weighing the move, our Ghost vs Substack comparison covers fees, features, and ownership. If your content lives on WordPress rather than Substack, the WordPress to Ghost migration guide walks that path. The importer is different; the destination is the same.
Frequently Asked Questions
Do my subscribers transfer from Substack to Ghost?
Will my paid subscriptions keep billing without re-subscribing?
How do I make sure no paid subscribers get lost in the move?
What does not transfer when I migrate to Ghost?
Why do I get a File Type Not Allowed error when importing my Substack export?
How do I fix the Could not find Stripe customer error when importing paid subscribers?
Do subscribers who paid through the Substack iOS app transfer to Ghost?
Why did imported members not receive my Ghost welcome email?
Keep reading
How to Migrate from WordPress to Ghost
Step-by-step WordPress to Ghost migration: what transfers, what does not, and how to handle images, redirects, SEO, and subscriber lists without losses.
Ghost vs Substack 2026: Fees, Features & Ownership
Ghost charges 0% revenue share; Substack takes 10% plus Apple in-app fees. Newsletters, design, SEO, pricing, and ownership compared side by side for 2026.
6 Best Substack Alternatives, Honestly Compared
The six real Substack alternatives — Ghost, beehiiv, Buttondown, Kit, WordPress, Medium — compared by fees, ownership, and design, with a pick for each case.
Ghost Portal Guide: Settings, Links & Customization
How Ghost's Portal works and how to shape it: signup options, default billing cycle, the floating button, every Portal link and data attribute, translation.
Recommended Themes
These themes excel at the features discussed in this article.
Comparing options? Browse all premium Ghost themes side by side.
Get every theme in one bundle
The complete Luxe Themes bundle — every theme, one purchase.