Title: Substack Importer
Author: WordPress.org
Published: <strong>11. Dezember 2020</strong>
Last modified: 22. April 2026

---

Search plugins

![](https://ps.w.org/substack-importer/assets/icon-256x256.png?rev=2527220)

# Substack Importer

 By [WordPress.org](https://profiles.wordpress.org/wordpressdotorg/)

[Download](https://downloads.wordpress.org/plugin/substack-importer.1.2.0.zip)

 * [Details](https://de-ch.wordpress.org/plugins/substack-importer/#description)
 * [Reviews](https://de-ch.wordpress.org/plugins/substack-importer/#reviews)
 *  [Installation](https://de-ch.wordpress.org/plugins/substack-importer/#installation)
 * [Development](https://de-ch.wordpress.org/plugins/substack-importer/#developers)

 [Support](https://wordpress.org/support/plugin/substack-importer/)

## Description

The Substack Importer will import content from an export file downloaded from your
Substack newsletter.

The following content will be imported:

 * Posts and images.
 * Podcasts.
 * Comments (only for publicly accessible posts).
 * Author information.

In the future, we plan to improve the importer by:

 * Mailing lists.
 * Enhancing the performance of processing export files with many posts and media.

### Development

For running unit tests and contributing to the plugin, see the [README on GitHub](https://github.com/wordpress/substack-importer#development).

Tests can be run with wp-env or with any local WordPress setup paired with a Docker
MySQL container. Run `composer install` first, then `vendor/bin/phpunit`.

### Hooks

The Substack Importer provides filters and actions at key stages of the content 
conversion pipeline.

#### Post-level Filters

### substack_importer_post_meta

Filter the post metadata loaded from the Substack API before it is used for author,
comments, and other post data.

Parameters:
 * `$post_meta` (array|null) – The post metadata from the Substack API
response. * `$post` (array) – The raw Substack post data from the CSV. * `$id` (
int) – The Substack post ID.

### substack_importer_raw_content

Filter the raw HTML content before Gutenberg conversion. Runs after the subtitle
has been prepended (if present). Useful for cleaning up Substack-specific HTML, 
adding custom elements, or stripping unwanted markup.

Parameters:
 * `$html_body` (string) – The raw HTML content from the Substack export.*`
$post` (array) – The raw Substack post data from the CSV. * `$post_meta` (array|
null) – The post metadata from the Substack API response.

### substack_importer_subtitle

Filter the subtitle HTML before it is prepended to the post content. Return an empty
string to skip the subtitle entirely.

Parameters:
 * `$heading` (string) – The subtitle HTML (default: an h2 element).*`
$post` (array) – The raw Substack post data.

### substack_importer_post_content_after_conversion

Filter the post content after Gutenberg conversion but before it is added to the
WXR. Useful for wrapping paywalled content in custom blocks (e.g., membership plugins).

Parameters:
 * `$post_content` (string) – The converted Gutenberg block content.*`
$post` (array) – The original Substack post data. * `$post_meta` (array|null) – 
Additional post metadata from Substack API.

### substack_importer_post_data

Filter the final post data array before it is added to the WXR.

Parameters:
 * `$post_data` (array) – The post data. * `$post` (array) – The original
Substack post data.

#### Content Conversion Filters

### substack_importer_converted_node

Filter the result of a single node conversion to a Gutenberg block. Allows modification
of the block name and attributes. Return a null block_name to skip the node.

Parameters:
 * `$block_data` (array) – Array with ‚block_name‘ and ‚block_attributes‘
keys. * `$node` (DOMElement) – The converted DOM node. * `$node_name` (string) –
The original HTML tag name (e.g. ‚p‘, ‚div‘, ‚h2‘).

### substack_importer_image_result

Filter the image node conversion result. Useful for adjusting image sizes, captions,
or link destinations.

Parameters:
 * `$result` (array) – Array with ‚block_attributes‘ and ’node‘ keys.*`
$image_data` (array|null) – The decoded image data from the Substack data-attrs 
attribute.

### substack_importer_pre_embed_conversion

Short-circuit the embed node conversion before default handling. Return a non-null
array to skip the built-in switch statement entirely. Useful for handling unsupported
embed types or overriding the default conversion for a specific provider.

Parameters:
 * `$pre_result` (array|null) – Return non-null to short-circuit. Expected
keys: ’node‘, ‚block_attributes‘, ‚block_name‘. * `$node` (DOMElement) – The embed
DOM node before conversion. * `$parent` (DOMElement) – The parent DOM element. *`
$first_class` (string) – The CSS class identifying the embed type (e.g. ‚youtube-
wrap‘, ‚tweet‘).

### substack_importer_embed_result

Filter the embed node conversion result after the default conversion. Useful for
modifying embed URLs, adding custom attributes, or changing how embeds are represented.

Parameters:
 * `$output` (array) – Array with ‚block_name‘, ‚block_attributes‘, 
and ’node‘ keys. * `$first_class` (string) – The CSS class identifying the embed
type.

### substack_importer_audio_block

Filter the Gutenberg audio block HTML for podcast posts.

Parameters:
 * `$block` (string) – The Gutenberg audio block HTML. * `$audio_url`(
string) – The URL of the podcast audio file.

#### Paywall Filters

### substack_importer_paywall_marker_text

Filter the paywall marker text that appears in the imported content.

Parameters:
 * `$marker_text` (string) – The default paywall marker text. * `$node`(
DOMElement) – The paywall node being converted. * `$parent` (DOMElement) – The parent
element.

### substack_importer_paywall_content

Filter the entire paywall conversion result. Return a non-null value to override
the default conversion.

Parameters:
 * `$result` (array|null) – The conversion result, null to use default.*`
$node` (DOMElement) – The paywall node being converted. * `$parent` (DOMElement)–
The parent element.

#### Actions

### substack_importer_before_post

Fires before a single Substack post is processed and converted. Useful for setting
up state or performing actions before conversion begins.

Parameters:
 * `$post` (array) – The raw Substack post data from the CSV. * `$post_meta`(
array|null) – The post metadata from the Substack API response. * `$id` (int) – 
The Substack post ID.

### substack_importer_after_post

Fires after a single Substack post has been converted and added to the WXR. Useful
for logging, progress tracking, or performing cleanup after each post.

Parameters:
 * `$post_data` (array) – The final post data that was added to the 
WXR. * `$post` (array) – The raw Substack post data from the CSV. * `$post_meta`(
array|null) – The post metadata from the Substack API response. * `$id` (int) – 
The Substack post ID.

## Installation

This plugin depends on the [WordPress Importer](https://wordpress.org/plugins/wordpress-importer)
plugin which needs to be installed first.

To install the Substack Importer:

 1. Upload the `substack-importer` directory to the `/wp-content/plugins/` directory
 2. Activate the plugin through the ‚Plugins‘ menu in WordPress

## FAQ

### After about 30 seconds, the import stops and I am seeing a blank screen. What happened?

When trying to import a large number of posts and images, timeouts can occur. To
solve this, you can try to run the import
 several times until all content has been
imported.

## Reviews

![](https://secure.gravatar.com/avatar/a5ab09149ebd10b755b69296f50117859bd7c36911b2f538e3d88f8a6aed4873?
s=60&d=retro&r=g)

### 󠀁[Missing some important options](https://wordpress.org/support/topic/missing-some-important-options/)󠁿

 [HollyJahangiri](https://profiles.wordpress.org/hollyjahangiri/) 10. Januar 2024

It worked. BUT… it should have an option to (a) make imported posts DRAFTS (even
if they were not Drafts in Substack); .(b) use the first image as the Featured Image
for imported posts; and (c) option to use import date as publish date so that they’re
easier to find (or, alternatively, to set a Category or Tag for all imported posts).
Yes, it times out. Not a fatal flaw, but maybe the ability to set a time-out value(
or post import speed) would be useful? I used it on the smaller of my two newsletters.
I don’t know that I’ll use it on the larger one unless the suggestions of (a), (
b), and (c) above are implemented soon.

![](https://secure.gravatar.com/avatar/79be49244f31b3cc7daa089b0044cea9edef19fd609b36bce6d0a3a1646f9c0f?
s=60&d=retro&r=g)

### 󠀁[Imports no content or images / No support](https://wordpress.org/support/topic/imports-page-names-but-not-the-content/)󠁿

 [mikeairhart](https://profiles.wordpress.org/mikeairhart/) 11. August 2023

This plugin does not work with WordPress 6.3:1. The page content is not imported,
only a portion of the page header is. 2. The importer reports an error on the first
image and makes no effort with other images. The developer has not responded to 
other support requests in two years.

![](https://secure.gravatar.com/avatar/eb52f35a586453bdb41c20594d9fc5baf13967d6325921b83bd277d93d745e77?
s=60&d=retro&r=g)

### 󠀁[Fatally Flawed — Dependent on Copyright Infringement](https://wordpress.org/support/topic/fatally-flawed-dependent-on-copyright-infringement/)󠁿

 [lisatann](https://profiles.wordpress.org/lisatann/) 10. Dezember 2021

This is a decent plugin in that it essentially does what it claims to. Although 
the documentation was sketchy (almost nonexistent), it was easy enough to do the
import. I downloaded a .zip file of my substack posts, then uploaded the same .zip
file to my WP site from Tools > Import > Substack. The import was pretty quick —
maybe 5 minutes at the most. I only started my substack 6 months ago so there wasn’t
a lot of data. Then bam! I had a whole bunch of new, published WP blog posts, with
the original substack date. (For the most part, that is — there were some date/time
issues when the original post was near midnight. I’m assuming that’s due to different
server times.) They came in with my site’s styling, which was impressive. Footnotes
were more or less there, but not exactly as footnotes; had I wanted to keep them,
I would have had to do some cleanup. My substack and blog are heavily dependent 
on images (I’m a photographer) and, although I could see the correct images in the
imported posts, I couldn’t find them in the Media Library. I use each post’s Featured
Image in several different ways and couldn’t figure out how to even find the images
that I could see in my posts. So I tracked them down. Turns out they are copies 
of my images and they live on an AWS server. I never gave the plugin permission 
to make copies of my images or to host them elsewhere. So that’s fatal flaw #1: 
I’ve completely lost control of my own images. They are on a server for which I 
have only Read permissions. I’ve already alluded to fatal flaw #2: The images aren’t
on my own server and therefore can’t be used as Featured Images in my posts. Fatal
flaw #3 would be that when AWS goes down (as it did a few days ago), all of those
images would be broken on my site. I unpublished all the newly created posts and
began replacing the images. So — aside from the fatal flaws mentioned above, it 
likely would have taken just as much time to create the posts manually.

 [ Read all 3 reviews ](https://wordpress.org/support/plugin/substack-importer/reviews/)

## Contributors & Developers

“Substack Importer” is open source software. The following people have contributed
to this plugin.

Contributors

 *   [ WordPress.org ](https://profiles.wordpress.org/wordpressdotorg/)

“Substack Importer” has been translated into 4 locales. Thank you to [the translators](https://translate.wordpress.org/projects/wp-plugins/substack-importer/contributors)
for their contributions.

[Translate “Substack Importer” into your language.](https://translate.wordpress.org/projects/wp-plugins/substack-importer)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/substack-importer/),
check out the [SVN repository](https://plugins.svn.wordpress.org/substack-importer/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/substack-importer/)
by [RSS](https://plugins.trac.wordpress.org/log/substack-importer/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.2.0

 * Compatibility: the plugin now requires PHP 7.4 or higher.
 * Enhancement: added new pre-import options for forcing Draft status, choosing 
   publish date mode, setting the first image as Featured Image, and applying a 
   global Category/Tag.
 * Enhancement: improved import behavior handling for featured image assignment 
   and post metadata processing during import.
 * Enhancement: added `substack_importer_paywall_marker_text` filter to customize
   paywall marker text.
 * Enhancement: added `substack_importer_paywall_content` filter to override paywall
   block conversion.
 * Enhancement: added `substack_importer_post_content_after_conversion` filter to
   modify content after Gutenberg conversion.
 * Enhancement: added `substack_importer_raw_content` filter to modify raw HTML 
   before Gutenberg conversion.
 * Enhancement: added `substack_importer_subtitle` filter to customize or skip the
   subtitle heading.
 * Enhancement: added `substack_importer_post_meta` filter to modify post metadata
   before processing.
 * Enhancement: added `substack_importer_converted_node` filter to customize individual
   block conversions.
 * Enhancement: added `substack_importer_image_result` filter to modify image block
   attributes.
 * Enhancement: added `substack_importer_embed_result` filter to modify embed block
   results after conversion.
 * Enhancement: added `substack_importer_pre_embed_conversion` filter to short-circuit
   embed conversion before default handling.
 * Enhancement: added `substack_importer_audio_block` filter to customize the podcast
   audio block.
 * Enhancement: added `substack_importer_before_post` action that fires before each
   post is processed.
 * Enhancement: added `substack_importer_after_post` action that fires after each
   post is added to the WXR.

#### 1.1.2

 * Enhancement: support captions for images.
 * Enhancement: support TikTok embeds
 * Compatibility: the plugin now requires PHP 7.2 or higher.
 * Fix: convert preformatted content to verse block.
 * Fix: twitter conversion bug.

#### 1.1.1

 * Tested up to WordPress 6.7
 * Fix: null checking

#### 1.1.0

 * Update `wxr-generator` to latest version. Fixes a bug where imports could error
   out due to a misformed timezone identifier.

#### 1.0.9

 * Use subtitle as post excerpt if not empty
 * Testing the plugin up to WordPress 6.4.2
 * Fix PHPCS error and cleanup composer.lock

#### 1.0.8

 * Removed the subscription input from post content

#### 1.0.7

 * Convert the paywall div to a paragraph

#### 1.0.6

 * Testing the plugin up to WordPress 6.2

#### 1.0.5

 * Add support for WordPress 6.1

#### 1.0.4

 * Fix Soundcloud embeds

#### 1.0.3

 * Identify authors for draft posts as «Draft Posts»

#### 1.0.2

 * Republishing to fix a CI error.

#### 1.0.1

 * Remove unnecessary load_meta_data line.
 * Fix embeds not displaying properly on website.

#### 1.0.0

 * Add post meta for paid content.
 * Convert Instagram embed to a link.
 * Add the subtitle as a H2 at the beginning of the post.
 * Set the correct comment_status for posts.

#### 0.1.0

 * Refactored the importer.
 * Add support for authors.
 * Add support for comments.
 * Conversion of content to Gutenberg blocks.
 * Convert the export to WXR and use the WordPress Importer plugin to import the
   WXR.
 * Add progress indicator
 * Add support for attachments.

#### 0.1

Early proof-of-concept version.

## Meta

 *  Version **1.2.0**
 *  Last updated **1 Monat ago**
 *  Active installations **900+**
 *  WordPress version ** 5.2 or higher **
 *  Tested up to **6.9.4**
 *  PHP version ** 7.4 or higher **
 *  Languages
 * [Chinese (Taiwan)](https://tw.wordpress.org/plugins/substack-importer/), [English (US)](https://wordpress.org/plugins/substack-importer/),
   [German](https://de.wordpress.org/plugins/substack-importer/), [Hebrew](https://he.wordpress.org/plugins/substack-importer/)
   und [Portuguese (Brazil)](https://br.wordpress.org/plugins/substack-importer/).
 *  [Translate into your language](https://translate.wordpress.org/projects/wp-plugins/substack-importer)
 * Tags
 * [importer](https://de-ch.wordpress.org/plugins/tags/importer/)[substack](https://de-ch.wordpress.org/plugins/tags/substack/)
 *  [Advanced View](https://de-ch.wordpress.org/plugins/substack-importer/advanced/)

## Ratings

 2 von 5 Sternen.

 *  [  0 5-Sterne-Rezensionen     ](https://wordpress.org/support/plugin/substack-importer/reviews/?filter=5)
 *  [  0 4-Sterne-Rezensionen     ](https://wordpress.org/support/plugin/substack-importer/reviews/?filter=4)
 *  [  1 3-Sterne-Rezension     ](https://wordpress.org/support/plugin/substack-importer/reviews/?filter=3)
 *  [  1 2-Sterne-Rezension     ](https://wordpress.org/support/plugin/substack-importer/reviews/?filter=2)
 *  [  1 1-Sterne-Rezension     ](https://wordpress.org/support/plugin/substack-importer/reviews/?filter=1)

[Your review](https://wordpress.org/support/plugin/substack-importer/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/substack-importer/reviews/)

## Contributors

 *   [ WordPress.org ](https://profiles.wordpress.org/wordpressdotorg/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/substack-importer/)