How I Built a Python Script That Automates My Entire Dev.to Publishing Workflow
I got tired of manually publishing articles to Dev.to. So I built a Python script that does it for me.
The Problem
I write articles in Markdown locally, then have to:
- Log into Dev.to
- Click "New Post"
- Copy-paste the content
- Set tags, preview, publish
- Repeat for every article
When you publish 5+ articles a day, this takes forever.
The Solution
A Python script that logs into Dev.to, grabs the CSRF token, and publishes articles programmatically.
import requests, re, html
s = requests.Session()
# Login
r = s.get('https://dev.to/enter')
token = re.search(r'authenticity_token.*?value="([^"]+)"', r.text).group(1)
s.post('https://dev.to/users/sign_in', data={{
'user[email]': EMAIL, 'user[password]': PASSWORD,
'authenticity_token': token,
}})
# Get CSRF from dashboard (NOT /new - Dev.to changed in 2026)
r = s.get('https://dev.to/dashboard')
csrf = re.search(r'authenticity_token.*?value="([^"]+)"', r.text).group(1)
# Publish
s.post('https://dev.to/articles', data={{
'authenticity_token': csrf,
'article[title]': title,
'article[body_markdown]': body,
'article[published]': '1',
}})
Key Insights
1. CSRF Location Changed
In 2026, Dev.to changed their frontend. The /new page no longer contains a static CSRF token. You MUST fetch it from /dashboard instead.
2. Session Persistence
Save cookies to a JSON file to avoid logging in every time:
import json
sess_data = {{'cookies': s.cookies.get_dict()}}
with open('devto_session.json', 'w') as f:
json.dump(sess_data, f)
3. Rate Limiting
Space articles 35 seconds apart. Dev.to rate-limits at about 4-5 articles per minute.
The Full Script
The complete script handles:
- Session management with cookie persistence
- CSRF token rotation
- Batch publishing with rate limiting
- Duplicate title detection
- Markdown frontmatter parsing
I packaged this into a reusable tool. If you want the full script with all features:
👉 Get the Dev.to Auto Publisher — $15 USDT (TRC-20)
USDT TRC-20: TNeUMpbwWFcv6v7tYHmkFkE7gC5eWzqbrs
Published str(int(time.time()))
Top comments (0)