How to Automate Social Media Posting with n8n
Use the official Postproxy n8n integration to publish to TikTok, Threads, Pinterest, and 6 more platforms from any workflow.
What’s missing in n8n’s native nodes
| Platform | Native n8n node |
|---|---|
| X (Twitter) | Yes, works |
| Personal only — company page is HTTP Request | |
| Page posts; no Reels or Stories | |
| Read-only; no Reels publish | |
| TikTok | None |
| YouTube | Upload only; no Shorts auto-detection |
| Threads | None |
| None | |
| Bluesky | None |
The realistic options: maintain HTTP Request nodes per platform with their per-platform OAuth, or use one node that abstracts all of them.
The Postproxy n8n integration
Postproxy is listed on n8n’s integrations directory. The integration is HTTP Request-based with credentials stored once and reused across workflows.
Setup:
- In n8n: Credentials → New → HTTP Header Auth (or HTTP Request with bearer auth)
- Name: “Postproxy”
- Header name:
Authorization - Header value:
Bearer YOUR_POSTPROXY_API_KEY
Then any HTTP Request node calling https://api.postproxy.dev/api/... reuses that credential.
For the official integration page, see postproxy.dev/automation/n8n and the integration listing on n8n.io.
Example workflow: RSS → social
A blog publishes a new post; the workflow scrapes the RSS feed, formats a caption, attaches the OG image, and posts to Instagram, LinkedIn, Threads, and X:
[RSS Trigger] → [Set node] caption = `${title}\n\n${summary}\n\nRead more: ${link}` image = `${ogImage}` → [HTTP Request: Postproxy] Method: POST URL: https://api.postproxy.dev/api/posts Auth: Postproxy credential (header) Body (JSON): { "post": { "body": "{{ $json.caption }}" }, "profiles": ["instagram", "linkedin", "threads", "twitter"], "media": ["{{ $json.image }}"] }Three logical nodes. Without a unified API the same workflow needs four separate platform nodes (or four HTTP Request nodes with hand-rolled OAuth refresh).
Conditional posting per platform
n8n’s Switch node plugs in cleanly:
[Webhook] → [Switch on type] ├─ "video" → [HTTP Request: Postproxy] │ body = { "post": {...}, "profiles": ["tiktok","instagram","youtube"], │ "media":[...], │ "platforms": { │ "tiktok": { "privacy_status": "PUBLIC_TO_EVERYONE" }, │ "instagram":{ "format": "reel" }, │ "youtube": { "privacy_status": "public" } │ } } ├─ "image" → [HTTP Request: Postproxy] │ body = { "post": {...}, "profiles": ["instagram","pinterest"], │ "media":[...], │ "platforms": { │ "pinterest": { │ "board_id": "987654321", │ "destination_link": "{{$json.url}}" │ } │ } } └─ "text" → [HTTP Request: Postproxy] body = { "post": {...}, "profiles": ["twitter","linkedin","threads"] }Same credential, three branches.
Status checks
Pair with a Wait + GET node, or use a Postproxy webhook → n8n Webhook trigger:
[HTTP Request: Postproxy create] → returns { id: "p_abc" } → [Wait 60 seconds] → [HTTP Request: GET /api/posts/{{ $json.id }}] → [If: status == "processed"] ├─ true → [Slack: post message "Published"] └─ false → [Slack: "Failed: " + error]The post-level status moves through processing → processed (or scheduled for future posts). Per-platform statuses are inside platforms[].status (processing, published, failed).
A real workflow: AI-generated → cross-posted
Combining n8n’s OpenAI / Anthropic nodes with the Postproxy POST makes a content pipeline:
[Cron: every Monday 9am] → [HTTP: fetch this week's product changelog] → [Anthropic: summarize into 3 social posts] → [Loop: for each post] → [HTTP Request: Postproxy] body = { "post": { "body": "{{ $json.text }}" }, "profiles": ["twitter", "linkedin", "threads"] }A weekly content drop. If the team prefers explicit review, insert a Slack approval step before the Postproxy node and only fire on approved reactions.
For the longer end-to-end version of this pipeline, see Building an AI content pipeline from generation to publishing.
Self-hosted n8n vs cloud
The setup is the same on both. Self-hosted n8n can also pull POSTPROXY_API_KEY from env vars and reuse it across workflows.
Troubleshooting
| Issue | Fix |
|---|---|
401 Unauthorized on first run | API key copied with whitespace, or wrong header (Authorization: Bearer ...) |
Post stuck in processing | Long video; check Postproxy dashboard for per-platform state |
Profile not found for X | The platform isn’t connected to your Postproxy account, or you passed an unrecognised network name |
Missing privacy_status (TikTok/YouTube) | TikTok and YouTube require privacy_status — set it in platforms |
Why n8n is a good fit
n8n’s strength is gluing things together with explicit, version-controllable workflows. Social media publishing has a lot of “happy path” and a lot of “what if a platform 429s.” n8n makes both visible. Putting the publish step behind one HTTP Request node — Postproxy — means the workflow stays readable.
Deeper reading: n8n tutorial workflow for a step-by-step build, and why n8n first on why we ship the n8n integration before others.