Most guides to leaving Substack treat the export file as the migration. It is the easy half. The export moves your posts and your list; it does not move your addresses, and addresses are what the archive is made of. A publication that arrives on Ghost with every post intact and every URL changed has not migrated, it has restarted.
This page sets out the order of operations, what the export leaves behind, and the redirect map that keeps the archive reachable.
The short answer
Export content and subscribers with all columns. Connect Stripe to Ghost before importing anyone. Get Substack’s revenue share removed before revoking its Stripe access, not after. Re-host the images. Upload a redirects.yaml with a negative lookahead so the /p/ rule does not collide with Ghost’s preview URLs. Verify with curl against real post URLs, with and without trailing slashes.
Then the one thing that is not a step: if the publication ran on a substack.com subdomain rather than a domain you own, the redirect map is not available to you at all, and no amount of care in the other eight steps changes that.
What the export actually contains
From Substack, Settings then Import / Export then Export your data produces a zip. Inside it: your posts as a CSV and as individual HTML files, your email list as a CSV, and a stats file.
What is not in it matters more:
- Images and media. The HTML files reference Substack’s CDN rather than embedding anything. The archive looks complete on your laptop because the pictures are still being served by the platform you are leaving.
- Subscriber names. Substack’s own documentation states that exporting a file with subscriber names is not currently possible. You are taking addresses, not identities.
- Notes, comment threads and drafts. None of the three are included.
| Asset | In the export | Survives the move | Notes |
|---|---|---|---|
| Post content | Yes, CSV and HTML | Yes | The easy half |
| Post URLs | No | Only with a redirect map | And only on an owned domain |
| Images and media | No, referenced only | Only if re-hosted | Still served by the platform you left |
| Subscriber addresses | Yes | Yes | Use the all-columns export |
| Subscriber names | No | No | Not currently exportable |
| Paid subscriptions | Via Stripe customer IDs | Yes, if the IDs travel | No card re-entry needed |
| Comments and threads | No | No | Archive them manually if they matter |
| Notes and drafts | No | No | Copy anything unpublished by hand |
| Open and click history | No | No | Segmentation restarts from zero |
| Recommendation network position | No | No | Not portable by design |
Reading down the third column is the honest summary of what a migration is. Two rows say yes unconditionally. The rest are conditional or lost, and the conditions were mostly set years before the migration was contemplated.
The subscriber export from the Subscribers page is the fuller one. The three-dot menu above the list offers Export, with a choice between all columns and visible columns only. All columns is the one you want, because it carries subscription status, plan, and the Stripe identifiers you need for the paid import.
Before you start: inventory the URLs
The redirect map is only as good as the list of old addresses it covers, and the list is not in the export file. Build it before the platform access goes away, because several of these sources disappear with it.
- Save the current sitemap. It is the fastest complete list of every post URL the platform knew about, and it stops existing when you leave.
- Export the stats file. It is in the content export and enumerates posts, including ones you had forgotten.
- Pull the Search Console Pages report for what was actually indexed, and the Links report for which URLs earned external links.
- Note the non-post URLs. The archive page, the about page, the subscribe page and any custom pages all have addresses that people have linked to.
- Record the feed URL. It is the single most commonly forgotten address on any migration, and subscribers cannot re-find it on their own.
Then sort by external links rather than by traffic. Traffic tells you what people are finding this month. Links tell you what the archive is worth, and a link is what a missing redirect actually destroys. The full method for building and verifying a map is on the redirects and URL stability reference page.
The order of operations
The sequence matters because two of these steps are difficult to reverse.
- Export content from Substack. If you are on a custom domain, Ghost’s importer is more reliable when pointed at the
yourname.substack.comsubdomain rather than the custom domain. - Export subscribers with all columns, so the Stripe customer IDs come with them.
- Connect Stripe to Ghost before importing anyone. Paid members cannot be imported into a publication with no payment processor attached.
- Import content and members into Ghost. Map the CSV fields, including the Stripe customer ID column. Members flagged with a complimentary plan carry gifted access across.
- Get Substack’s revenue share removed. This is the step people skip. Substack continues taking 10 percent of existing paid subscriptions after you have left, because those subscriptions still run through the Stripe connection it holds. Ghost’s migration documentation directs publishers to
[email protected]for help getting the fees removed. - Then disconnect Substack from Stripe. Revoke access at
dashboard.stripe.com/account/applications. Doing this before the fees are removed leaves you unable to resolve them and risks subscriptions falling out of sync. - Fix the Stripe statement descriptor. Depending on how the account was set up it may still read Substack, which is what your paying members see on their card statements. It is changed in Stripe’s public details settings.
- Re-host the images before the old CDN references matter.
- Upload the redirect map.
What breaks on paid subscriptions
Less than people fear, and in one specific place.
Substack bills through your own Stripe account, so the billing relationships already sit in a system you control. That is why the paid migration works at all: the subscriptions do not have to be recreated, only re-associated. Members are not asked to re-enter card details, provided the Stripe customer IDs travel with the import.
The failure mode is a mismatch. If the Stripe customer ID column is missing, malformed, or the members were imported before Stripe was connected, Ghost imports them as free members and reports the paid ones as skipped. The recovery is another import with corrected data, which is tedious rather than dangerous, but it is worth getting right the first time on a list of any size.
The genuinely unrecoverable item is the 10 percent. Every billing cycle that runs between your migration and the fee removal is a cycle you paid a platform you had already left.
Re-hosting the media
This step is easy to defer and expensive to skip, because nothing appears broken while you are deferring it.
The exported HTML references images on the platform’s CDN rather than embedding them. After import, the archive renders correctly on Ghost while every image is still being fetched from the platform you have left. The archive looks complete and is not.
Three consequences follow. You are dependent on a former vendor continuing to serve assets for a publication that no longer pays it. Every page load leaks a request to a domain you do not control, which is a performance cost on the Craft dimension as well as a dependency. And the day those references stop resolving, the failure is silent and retroactive across the entire archive at once.
The work is mechanical: crawl the imported posts for external CDN references, download each asset, upload it to Ghost’s own image storage, then rewrite the reference in the post body. It is worth scripting against the Ghost Admin API rather than doing by hand on any archive above a few dozen posts. Verify afterwards by loading a sample of old posts with the former CDN’s domain blocked in DevTools, which turns a silent future failure into a visible present one.
The send is the part nobody tests
Content and members can import perfectly and the first newsletter still fail to arrive, because delivery is a separate system from either.
An imported list has no sending history with your new configuration. The addresses are the same, the engagement record is not, and the sending domain may be new. That makes the first send after a migration the highest-risk send the publication will ever make.
Three things to settle before it goes out:
- Sending domain and authentication. A sending domain has to be verified, and SPF and DKIM configured so that at least one aligns with the From domain. Authentication passing is not the same as authentication aligning, and platforms report the first while saying nothing about the second. The requirements and the verification method are on the email authentication reference page.
- A test to an external seed address. Sending to your own inbox on the same domain bypasses most of the checks you are trying to test. Use an address at a different provider and read the full headers.
- An announcement send before a normal one. Subscribers who receive an unfamiliar From address with no explanation reach for the spam button, and on a list of any size a handful of complaints is enough to matter. The arithmetic is on the same reference page and it is worse at small volume than most publishers expect.
How much of this a platform handles for you is the main practical difference between them, and it is compared directly in email platforms ranked by what they cost the distribution loop.
The redirect map
Substack serves public posts at /p/post-slug. Ghost serves posts at /post-slug/. Every inbound link, every citation, and every indexed URL you have accumulated points at the first pattern.
There is a complication that catches people, and it is the reason this cannot be a single blanket rule: Ghost also uses /p/, for post previews. A rule that rewrites everything under /p/ will interfere with Ghost’s own preview URLs.
The way around it is a negative lookahead that excludes the UUID pattern Ghost uses for previews while matching the human-readable slugs Substack used. Ghost’s own Medium migration documentation uses the same technique to protect /p/, which is a reasonable signal that it is the intended approach.
Ghost reads redirects from a redirects.yaml file uploaded in Ghost Admin under Settings, Advanced, Labs. The file has two top-level keys, 301 and 302. A new publication has none by default, and uploading an empty file clears every rule, so download the current file before editing rather than writing a fresh one from memory.
301:
^/p/(?![0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})([^/]+)/?$: /$1/
^/archive/?$: /
^/about/?$: /about/
302:
The first line is the one doing the work. It matches /p/anything-that-is-not-a-uuid and sends it to /anything-that-is-not-a-uuid/, leaving Ghost’s preview URLs alone.
Test it with curl -I against a handful of real post URLs before trusting it, and check both with and without the trailing slash. Ghost enforces trailing slashes in most configurations, and a rule that fires on one form and not the other will leave half your archive returning 404.
Why 301 rather than 302 is covered in the reference page on redirects and URL stability, along with the reasons not to chain them and not to point a retired archive at the home page.
The redirect map only works if you owned the domain
This is the part that determines whether any of the above is available to you.
If your publication ran on a custom domain, you keep the domain, you point its DNS at Ghost, and the redirect map above does its job. Every link anyone ever made still resolves.
If your publication ran on yourname.substack.com, those URLs are not yours. You cannot upload a redirect file for a hostname you do not control, and whatever is served there after you leave is Substack’s decision rather than yours. The archive can be copied, but the addresses cannot be brought along, and every accumulated link points at a property you have walked away from.
There is no fix for this after the fact. It is decided years earlier, on the day the publication is set up, by whether a domain was registered.
What to do if you are in that position
The addresses cannot be recovered, and the situation can still be handled better or worse.
- Publish a final post on the old publication stating where the work now lives, with a link. It is the only redirect available to you, it requires a reader to act, and it is better than silence.
- Keep the old publication in place rather than deleting it. A live page with a pointer preserves some of the value of every existing link. A deleted one converts all of them into errors.
- Email the list directly about the move, more than once, before the old sending stops. The list is the one asset that is genuinely portable, so use it.
- Register the domain now and never repeat this. The rest of the archive, from today forward, can be portable even though the existing archive is not.
None of that recovers the accumulated position. It is triage, and the reason to write it down is that the alternative is doing nothing.
How this is scored
Two dimensions of the rubric move on a migration like this one.
Owned hub strength asks whether the publisher owns the ground the work sits on. The top band requires that the archive can be rebuilt and rehosted from source without losing a single URL. A Substack publication on a custom domain, migrated with a working redirect map and re-hosted media, can reach it. The same publication on a substack.com subdomain cannot, regardless of how well the move is executed, because the URLs were never portable.
Compounding asks whether the archive gains value as it grows. This is where the redirect map earns its place ahead of the export file. An archive that has kept its addresses through a platform change keeps everything those addresses have accumulated. An archive that has not starts its accumulation over on the day of the move, and the writing is identical either way.
The distinction the rubric is drawing is not between platforms. It is between publishers who can leave and publishers who cannot.
Verification checklist
Run all of these after the map is uploaded and before announcing the move. Each one has been the thing that was broken on a real migration.
- A sample of ten old post URLs return a single-hop 301 to the correct new address. Check with
curl -I -Land confirm the hop count is one, not two. - The same ten URLs work both with and without a trailing slash.
- The old feed URL redirects to the new feed, and the new feed validates.
- Feed autodiscovery is present in the head of the article template, not only the home page.
- The new sitemap lists destination URLs only, with no redirecting URLs in it.
- Ghost’s own
/p/preview URLs still work, which is what the negative lookahead exists to protect. - A sample of old posts render with the former CDN’s domain blocked.
- The Stripe statement descriptor shows your name rather than the old platform’s.
- A paid member’s account shows the correct tier and next billing date.
- A test send to an external address passes SPF, DKIM and DMARC, and shows no via indicator in Gmail.
Questions
Will paid subscribers have to re-enter their card details?
No, provided the Stripe customer IDs travel with the import and Stripe is connected to Ghost before members are imported. The billing relationships already live in your own Stripe account, which is why they can be re-associated rather than recreated.
How long does Substack keep taking its 10 percent?
Until the fee is removed from the Stripe connection, which is a support request rather than a setting. Every billing cycle between the migration and the removal is a cycle paid to a platform you have already left, and revoking Stripe access first makes it harder to resolve rather than easier.
Can I migrate without a custom domain and add one later?
You can add a domain to the new publication at any time, and it will not retroactively make the old subdomain URLs yours. The archive from the move forward becomes portable. Everything published before it stays where it is.
Should I keep publishing on both during the transition?
Briefly and deliberately, if at all. Duplicate content across two live archives creates a canonicalisation problem on top of a migration, and the correct answer is a clean cutover with a pointer left behind rather than a period of parallel publishing.
Is Ghost the only destination this applies to?
The order of operations, the export gaps, the media problem and the domain question apply to any destination. Only the redirect syntax and the /p/ collision are Ghost-specific. The platform-level trade between Ghost and the alternative most publishers weigh it against is in Ghost vs WordPress for a one-person publication.
Sources
- Ghost Developer Docs, Migrating from Substack
- Substack Support, How do I export my email list
- Ghost, Implementing redirects
Export behaviour, fee terms and redirect syntax verified August 4, 2026. Both platforms change their tooling, and the /p/ collision in particular depends on Ghost’s current preview URL scheme, so re-check the pattern against a live install before relying on it.