Skip to content

anyrxo/substack-tool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Substack Tool

An open-source CLI, TypeScript SDK, and MCP server for automating Substack. Built for AI agents and developers who need programmatic access to Substack's platform.

Substack doesn't offer a public API. This tool uses reverse-engineered internal endpoints to provide full automation capabilities: create posts, publish notes, manage subscribers, view analytics, and more.

This is a community tool. Fork it, extend it, build on top of it. Not affiliated with Substack Inc.

Features

Feature CLI SDK MCP
Authentication (cookie / email+password)
Create posts (draft or publish)
Publish drafts
List posts (published / drafts)
Delete posts
Create notes
List notes
Like notes
Restack notes
List subscribers
Subscriber stats
Profile info
Post analytics

Installation

# Install globally
npm install -g substack-tool

# Or use npx
npx substack-tool --help

Getting Your Auth Cookie

This tool authenticates using Substack's session cookie (connect.sid). Here's how to get it:

  1. Log in to substack.com in your browser
  2. Open DevTools (F12 or Cmd+Shift+I)
  3. Go to ApplicationCookieshttps://substack.com
  4. Find the connect.sid cookie
  5. Copy its value (starts with s%3A...)

⚠️ Keep this cookie private. It grants full access to your Substack account. Never commit it to version control. Store it in an environment variable.

export SUBSTACK_COOKIE="connect.sid=s%3A..."

CLI Usage

Authentication

# Login with cookie (recommended)
substack-tool auth login --cookie "connect.sid=s%3A..."

# Login with email/password (experimental)
substack-tool auth login --email you@example.com --password "yourpassword"

# Check auth status
substack-tool auth status

Posts

# Create a draft
substack-tool post create --title "My Post Title" --body "<h1>Hello World</h1><p>This is my post.</p>"

# Create from a Markdown file and publish immediately
substack-tool post create --title "Weekly Update" --file ./post.md --publish

# List published posts
substack-tool post list --status published

# List drafts
substack-tool post list --status draft

Notes

# Post a note
substack-tool note create --body "Interesting thought of the day..."

# List recent notes
substack-tool note list --limit 10

Subscribers

# List subscribers
substack-tool subscribers list --limit 50

SDK Usage (TypeScript/JavaScript)

Use the SDK in your own projects for programmatic Substack automation.

npm install substack-tool
import { Substack } from 'substack-tool';

const client = new Substack({
  cookie: process.env.SUBSTACK_COOKIE
});

// Create a draft post
const draft = await client.createPost({
  title: 'Automated Post',
  body: '<p>Published by an AI agent.</p>',
  draft: true
});
console.log(`Draft created: #${draft.id}`);

// Publish it
await client.publishPost(draft.id);

// Post a note
await client.createNote('Just published a new post!');

// Get subscriber count
const stats = await client.getSubscriberStats();
console.log(`Subscribers: ${stats.count}`);

// Get post analytics
const analytics = await client.getPostAnalytics(draft.id);
console.log(`Views: ${analytics.views}, Likes: ${analytics.likes}`);

// List recent notes
const notes = await client.listNotes(10);
notes.forEach(n => console.log(`- ${n.body}`));

All SDK Methods

Method Description
login(email, password) Authenticate with email/password
getCookie() Get current session cookie string
listPosts(status, limit, offset) List posts (published/draft/all)
createPost({ title, body, draft }) Create a new post
publishPost(draftId) Publish a draft
deletePost(id) Delete a post
listNotes(limit) List recent notes
createNote(body) Create a note
likeNote(noteId) Like a note
restackNote(noteId) Restack (repost) a note
listSubscribers(limit) List subscribers
getSubscriberStats() Get subscriber count/growth
getProfile() Get your profile info
getPostAnalytics(postId) Get post view/like/comment stats

MCP Server (for AI Agents)

This tool includes a Model Context Protocol (MCP) server, allowing AI agents like Claude, GPT, or any MCP-compatible client to automate Substack through natural language.

Setup with Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "substack": {
      "command": "npx",
      "args": ["-y", "substack-tool", "--mcp"],
      "env": {
        "SUBSTACK_COOKIE": "connect.sid=s%3A..."
      }
    }
  }
}

Or if installed globally:

{
  "mcpServers": {
    "substack": {
      "command": "substack-mcp",
      "env": {
        "SUBSTACK_COOKIE": "connect.sid=s%3A..."
      }
    }
  }
}

Available MCP Tools

Tool Description
substack_auth_status Check authentication status
substack_list_posts List posts with status filter
substack_create_post Create a post (draft or published)
substack_publish_post Publish a draft by ID
substack_delete_post Delete a post by ID
substack_create_note Create a short-form note
substack_list_notes List recent notes
substack_like_note Like a note
substack_restack_note Restack (share) a note
substack_list_subscribers List publication subscribers
substack_get_subscriber_stats Get subscriber growth stats
substack_get_profile Get profile information
substack_get_post_analytics Get analytics for a post

Example Prompts (with Claude/GPT)

Once connected via MCP, you can say things like:

  • "Create a draft post titled 'Weekly AI Roundup' with a summary of this week's AI news"
  • "Post a note saying 'New article just dropped! Check it out.'"
  • "Show me my subscriber count"
  • "List my last 5 published posts and their view counts"
  • "Publish my draft #12345"

REST API (Self-Hosted)

If you need a REST API (for webhooks, n8n, Make, Zapier, etc.), you can run the SDK behind a simple Express server:

import express from 'express';
import { Substack } from 'substack-tool';

const app = express();
app.use(express.json());

const client = new Substack({ cookie: process.env.SUBSTACK_COOKIE });

app.post('/api/posts', async (req, res) => {
  const post = await client.createPost(req.body);
  res.json(post);
});

app.post('/api/notes', async (req, res) => {
  const note = await client.createNote(req.body.body);
  res.json(note);
});

app.get('/api/subscribers', async (req, res) => {
  const subs = await client.listSubscribers();
  res.json(subs);
});

app.listen(3000, () => console.log('Substack API running on :3000'));

Development

git clone https://github.com/anyrxo/substack-tool.git
cd substack-tool
npm install
npm run build

# Run CLI locally
node dist/cli.js --help

# Run MCP server locally
SUBSTACK_COOKIE="..." node dist/mcp.js

How It Works

Substack doesn't provide a public API, but their web app makes internal API calls that can be observed and replicated. This tool:

  1. Authenticates using your session cookie (the same one your browser uses)
  2. Makes the same HTTP requests that Substack's web interface makes
  3. Parses the JSON responses into typed TypeScript objects

This is the same approach used by browser extensions, automation tools, and integrations across the industry. We're not bypassing any security measures; we're simply making the same requests your browser already makes.

For detailed endpoint documentation, see docs/api-reference.md.


Troubleshooting

"Unauthorized" or "403" errors Your connect.sid cookie has expired. Get a fresh one from your browser. Cookies typically last a few weeks but may expire sooner.

Notes not posting Substack Notes use a ProseMirror document format internally. The SDK handles this conversion automatically, but complex formatting (images, embeds) in notes may not be supported yet.

Rate limiting Substack may rate-limit rapid requests. Add delays between bulk operations. The SDK doesn't currently handle rate limiting automatically.


Disclaimer

This project is not affiliated with, endorsed by, or associated with Substack Inc. in any way.

This is an independent, community-driven, open-source tool created for educational and research purposes. It uses Substack's internal (undocumented) API endpoints, which are not officially supported and may change or break at any time without notice.

By using this tool, you acknowledge that:

  • You are solely responsible for how you use it
  • You must comply with Substack's Terms of Service
  • Automated access to Substack may violate their terms; use at your own risk
  • The authors and contributors accept no liability for any consequences of using this tool
  • This tool is provided "as is" without warranty of any kind

This project is intended for educational purposes, to demonstrate how web APIs work and how automation tools can be built. If Substack releases an official API, this tool should be migrated to use it.

If you are from Substack and have concerns about this project, please open an issue and we will address them promptly.

Contributing

PRs welcome. Please open an issue first to discuss what you want to change.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors