plugins/pm-writers/skills/substack-notes-scraper/SKILL.md
Scrapes a Substack Notes page and exports engagement data to a formatted .xlsx file. Use when asked to download, analyse, or export Substack Notes performance data including likes, comments, and restacks. Produces a formatted spreadsheet with conditional formatting, summary stats, and per-note engagement metrics.
npx skillsauth add mohitagw15856/pm-claude-skills substack-notes-scraperInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Substack has no public API for Notes analytics. You can't see likes, comments, and restacks in one place without scrolling through your feed manually. This skill scrapes the rendered Notes page, filters to only your original content, and exports everything to a spreadsheet you can actually analyze.
Credit: Originally created by a Substack newsletter author — adapted and extended for this library.
| Input | Format | Example |
|---|---|---|
| Notes URL | Full URL to the Notes tab | https://substack.com/@handle/notes |
| Author handle or name | Exact handle or display name | @handle or Jane Smith |
| Date range | Plain English or explicit range | last 30 days or Jan 2026 – Mar 2026 |
Claude will ask for these if not provided upfront.
substack-notes-[handle]-[YYYY-MM-DD].xlsx
| Column | Description |
|---|---|
| Date | Publication date (YYYY-MM-DD) |
| Text Preview | First 200 characters of the note |
| Full Text | Complete note text |
| Likes | Like count at time of scrape |
| Comments | Comment count |
| Restacks | Restack count |
| Total Engagement | Likes + Comments + Restacks |
| Link | Direct URL to the note |
| Note Type | original or restack |
Formatting applied:
#FFF2CC)Scrape Date: [YYYY-MM-DD HH:MM UTC]
Author: [handle]
Date Range: [start] – [end]
Total Notes: [n]
Original Notes: [n]
Restacks Filtered: [n]
Avg Likes: [n.n]
Avg Comments: [n.n]
Avg Restacks: [n.n]
Avg Total Eng: [n.n]
Best Note (Likes): [date] — [first 80 chars] — [n] likes
Best Note (Eng): [date] — [first 80 chars] — [n] total engagement
Confirm the three required inputs are present. If any are missing, ask before proceeding. Parse the date range into a concrete start date and end date (convert relative ranges like "last 30 days" to explicit dates using today's date).
Use WebFetch to load the Notes URL. Substack Notes pages are JavaScript-rendered — request the full rendered HTML. If WebFetch returns a skeleton page without note content, note this in your response and ask the user to paste the page HTML manually or confirm browser access is available.
Substack Notes load incrementally. Repeat fetching or scrolling until either:
Rate-limit: wait 2 seconds between each paginated request. Do not hammer the endpoint.
For every note element found on the page, extract:
original if the author matches the specified author; restack if it belongs to someone elseKeep ALL rows in the data (restacks included as rows with Note Type = restack). The Summary sheet stats should count only original notes. Mark restacks clearly so the user can filter them out themselves in Excel if preferred.
Apply date filter: exclude any note outside the specified date range.
For each row: Total Engagement = Likes + Comments + Restacks
Sort original notes by Likes descending. Mark the top 20% (round up) for conditional formatting. These rows will be highlighted yellow in the output file.
Use Python with openpyxl to generate the file. Structure:
# Required libraries
import openpyxl
from openpyxl.styles import PatternFill, Font, Alignment
from openpyxl.utils import get_column_letter
from datetime import datetime
# Sheet 1: Notes Data
# - Write header row, bold, freeze row 1
# - Write all data rows
# - Apply auto-filter: ws.auto_filter.ref = ws.dimensions
# - Apply yellow fill to top-20% rows by likes
# - Auto-size columns (iterate cells to find max length)
# Sheet 2: Summary
# - Write summary stats as key-value pairs, no table format
Name the file substack-notes-[handle]-[YYYY-MM-DD].xlsx using today's date.
After generating the file, report:
original notes, not restacksdevelopment
Analyse competitor moves and translate them into strategic implications for your product roadmap. Use when a competitor announces a new feature, pricing change, partnership, or strategic shift, or when producing a periodic competitive intelligence report. Produces a categorised signal analysis with reactive-vs-proactive assessment, threat ratings, specific roadmap implications, and recommended responses with owners.
development
Build a community management playbook for a brand's social media channels. Use when asked to create guidelines for managing comments, DMs, and community interactions, define a moderation policy, or build response frameworks for social media community managers. Produces a complete playbook with response templates, escalation paths, moderation rules, and tone guidelines.
development
Activate a 4-stage coding discipline framework that forces Claude to plan before coding, isolate changes on a branch, write tests first, and self-review output twice before presenting it. Use when starting a complex coding task, when past Claude sessions produced broken first drafts, or when you want to prevent rework cycles. Produces a confirmed written plan, isolated feature branch, test-first implementation, and a double-reviewed output with a correctness and code-quality checklist.
development
Optimize an article for Answer Engine Optimization (AEO) — restructuring content so AI engines like ChatGPT, Perplexity, and Claude can extract, quote, and cite it. Rewrites headings as questions, drops 50-80 word answer capsules, audits paragraph length, and flags trust signals. Use when asked to AEO-optimize, make content AI-readable, improve AI citation chances, or adapt an article for answer engines.