
Research
/Security News
DuckDB npm Account Compromised in Continuing Supply Chain Attack
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
n8n-nodes-meta-publisher
Advanced tools
Publish to Instagram, Facebook Pages, and Threads (images, videos, reels, stories, carousels) via Meta Graph APIs.
Publish to Instagram, Facebook Pages, and Threads from n8n — including Images, Videos, Reels, Stories, and Carousels — with a single, DRY node.
Built from the official n8n community node starter structure so you can develop, lint, and ship confidently.
One node to publish across Instagram / Facebook Pages / Threads
Create → poll → publish workflow handled for you
Reels, Stories, Carousels (IG) + Photos/Videos (FB) + Text/Image/Video/Carousel (Threads)
Two input styles:
Consistent JSON output (status, IDs, permalinks-ready payloads)
Friendly polling with jitter; configurable timeouts
Facebook Pages
Threads
n8n-node-meta-publisher
via n8n Community Nodes.Add a credential in n8n called Meta Graph API with an Access Token (prefer long-lived). The node will also attempt OAuth2 if configured in your instance, then fall back to the access token.
Keep tokens in Credentials, not in node fields. This keeps secrets secure and reusable across workflows.
Drag Meta Publisher into your workflow.
Choose Resource:
Choose Operation (e.g., Publish Reel).
Fill required fields (e.g., IG User ID, Media URL, Caption).
Optionally adjust Polling Interval and Max Wait.
Run the workflow.
Example (IG → Publish Image)
1789…
https://…/photo.jpg
Hello from n8n 🚀
Instead of filling parameters in the node UI, you can set Input Source = JSON Property. This allows you to feed one or more publishing jobs from the incoming item JSON.
From JSON Property
$json
to pass the entire input item.data.post
if your jobs are nested inside {"data": { "post": {...}}}
.Each job must be an object with at least:
resource
: "instagram" | "facebook" | "threads"
operation
: one of the supported operationsresource
– platform to publish tooperation
– type of publish actionpollSec
(optional) – polling interval (default: 2
)maxWaitSec
(optional) – max wait before timeout (default: 300
)All Instagram jobs require:
igUserId
– Instagram Business User IDautoPublish
(default: true)Operations:
publishImage
→ mediaUrl
, caption?
publishVideo
→ mediaUrl
, caption?
, coverUrl?
publishReel
→ videoUrl
, caption?
, thumbOffsetMs?
, shareToFeed?
publishStory
→ mediaUrl
, storyKind
("image"
| "video"
), caption?
publishCarousel
→ items[]
({ type: "image|video", url: "..." }
), caption?
All Facebook jobs require:
pageId
– Page IDOperations:
publishFbPhoto
→ imageUrl
, caption?
publishFbVideo
→ videoUrl
, title?
, description?
All Threads jobs require:
thUserId
(or userId
alias) – Threads User IDOperations:
threadsPublishText
→ text
threadsPublishImage
→ imageUrl
, text?
, altText?
threadsPublishVideo
→ videoUrl
, text?
, altText?
threadsPublishCarousel
→ items[]
({ type: "image|video", url: "...", altText? }
), text?
You can also pass an array of jobs to publish multiple posts in one execution.
[
{
"resource": "instagram",
"operation": "publishStory",
"igUserId": "112233445566",
"mediaUrl": "https://www.example.com/video.mp4",
"caption": "This is an example caption.",
"storyKind": "video",
"autoPublish": true
},
{
"resource": "instagram",
"operation": "publishStory",
"igUserId": "112233445566",
"mediaUrl": "https://www.example.com/image.jpg",
"caption": "This is an example caption.",
"storyKind": "image",
"autoPublish": true
},
{
"resource": "instagram",
"operation": "publishImage",
"igUserId": "112233445566",
"mediaUrl": "https://www.example.com/image.jpg",
"caption": "This is an example caption.",
"autoPublish": true
},
{
"resource": "instagram",
"operation": "publishVideo",
"igUserId": "112233445566",
"mediaUrl": "https://www.example.com/video.mp4",
"caption": "This is an example caption.",
"coverUrl": "https://www.example.com/image.jpg",
"autoPublish": true
},
{
"resource": "instagram",
"operation": "publishReel",
"igUserId": "112233445566",
"videoUrl": "https://www.example.com/video.mp4",
"caption": "This is an example caption.",
"thumbOffsetMs": 0,
"shareToFeed": true,
"autoPublish": true
},
{
"resource": "instagram",
"operation": "publishCarousel",
"igUserId": "112233445566",
"items": [
{
"type": "image",
"url": "https://www.example.com/image.jpg",
"caption": "This is an example caption."
},
{
"type": "video",
"url": "https://www.example.com/video.mp4",
"caption": "This is an example caption."
}
],
"caption": "This is an example caption.",
"autoPublish": true
},
{
"resource": "facebook",
"operation": "publishFbPhoto",
"pageId": "112233445566",
"imageUrl": "https://www.example.com/image.jpg",
"caption": "This is an example caption."
},
{
"resource": "facebook",
"operation": "publishFbVideo",
"pageId": "112233445566",
"videoUrl": "https://www.example.com/video.mp4",
"title": "This is an example title.",
"description": "This is an example description."
},
{
"resource": "facebook",
"operation": "publishFbStoryPhoto",
"pageId": "112233445566",
"imageUrl": "https://www.example.com/image.jpg"
},
{
"resource": "facebook",
"operation": "publishFbStoryVideo",
"pageId": "112233445566",
"videoUrl": "https://www.example.com/video.mp4"
},
{
"resource": "facebook",
"operation": "publishFbReel",
"pageId": "112233445566",
"videoUrl": "https://www.example.com/video.mp4",
"description": "FB Reel Description"
},
{
"resource": "threads",
"operation": "threadsPublishText",
"thUserId": "112233445566",
"text": "This is an example text."
},
{
"resource": "threads",
"operation": "threadsPublishImage",
"thUserId": "112233445566",
"imageUrl": "https://www.example.com/image.jpg",
"text": "This is an example caption.",
"altText": "This is an example alt text."
},
{
"resource": "threads",
"operation": "threadsPublishVideo",
"thUserId": "112233445566",
"videoUrl": "https://www.example.com/video.mp4",
"text": "This is an example caption.",
"altText": "This is an example alt text."
},
{
"resource": "threads",
"operation": "threadsPublishCarousel",
"thUserId": "112233445566",
"items": [
{
"type": "image",
"url": "https://www.example.com/image.jpg",
"altText": "This is an example alt text.",
"caption": "This is an example caption."
},
{
"type": "video",
"url": "https://www.example.com/video.mp4",
"altText": "This is an example alt text.",
"caption": "This is an example caption."
}
],
"text": "This is an example caption."
}
]
{
"resource": "instagram",
"operation": "publishImage",
"igUserId": "112233445566",
"mediaUrl": "https://example.com/image.jpg",
"caption": "My first IG post",
"autoPublish": true
}
Every successful publish returns a consistent JSON shape (fields may vary slightly by resource/operation):
{
"resource": "instagram|facebook|threads",
"type": "image|video|reel|story|carousel|text",
"creationId": "1789...", // IG/Threads container or parent (when applicable)
"children": ["childId1"], // for carousels
"status": "FINISHED|PUBLISHED|READY|ERROR|...",
"published": true,
"publishResult": { "id": "1790..." }, // media/thread object
"videoId": "1234567890" // FB video id when relevant
}
Use this to chain downstream steps (e.g., fetch permalink, store IDs).
The Meta Publisher Utils node generates a ready-to-run JSON payload for the Meta Publisher node. It’s perfect for assembling multiple posts (IG/FB/Threads) from a single set of inputs, templates, or upstream data.
You select:
You provide common inputs (e.g., imageUrl
, videoUrl
, caption
, IDs)
The node outputs one item whose json.data
is an array of jobs ready for the Meta Publisher node’s JSON input mode.
From JSON Property
data
That’s it—Meta Publisher will execute each generated job in the array.
Drop Meta Publisher Utils.
In Resources, tick Instagram and Threads.
In Instagram Operations, tick Publish Image and Publish Reel.
Fill:
1789…
https://example.com/image.jpg
https://example.com/reel.mp4
Hello from n8n
In Threads Operations, tick Publish Text:
9876…
Posting from n8n 💚
(Optional) Leave Skip Missing enabled to silently skip incomplete jobs.
Connect to Meta Publisher (JSON mode as above) and run.
The Utils node will output something like:
{
"data": [
{
"resource": "instagram",
"operation": "publishImage",
"igUserId": "1789...",
"mediaUrl": "https://example.com/image.jpg",
"caption": "Hello from n8n",
"autoPublish": true
},
{
"resource": "instagram",
"operation": "publishReel",
"igUserId": "1789...",
"videoUrl": "https://example.com/reel.mp4",
"caption": "Hello from n8n",
"thumbOffsetMs": 0,
"shareToFeed": true,
"autoPublish": true
},
{
"resource": "threads",
"operation": "threadsPublishText",
"thUserId": "9876...",
"text": "Posting from n8n 💚"
}
],
"count": 3
}
Resources (multi-select):
Operations (checkboxes shown only when the resource is selected):
publishStory
, publishImage
, publishVideo
, publishReel
, publishCarousel
publishFbPhoto
, publishFbVideo
threadsPublishText
, threadsPublishImage
, threadsPublishVideo
, threadsPublishCarousel
Common inputs: imageUrl
, videoUrl
, caption
Per-resource IDs: igUserId
, pageId
, thUserId
Extras:
coverUrl
(video), reelVideoUrl
, thumbOffsetMs
, shareToFeed
, igItems
(carousel)storyImageUrl
, storyVideoUrl
(if omitted, falls back to common URLs)text
, altText
, thItems
(carousel: image/video entries with altText
, optional caption
)Behavior toggles:
Tip: When building carousels, supply at least 2 items; the Utils node will warn/skip otherwise (depending on Skip Missing).
Upstream nodes (e.g., Set, Spreadsheet File, HTTP Request) can provide per-item fields like igUserId
, imageUrl
, etc. Use n8n expressions in the Utils node (e.g., ={{$json.imageUrl}}
) to populate the payload dynamically.
Instagram → Image
{
"resource": "instagram",
"operation": "publishImage",
"igUserId": "1789...",
"mediaUrl": "https://example.com/photo.jpg",
"caption": "My IG post",
"autoPublish": true
}
Instagram → Story (video)
{
"resource": "instagram",
"operation": "publishStory",
"igUserId": "1789...",
"mediaUrl": "https://example.com/story.mp4",
"caption": "Story time",
"storyKind": "video",
"autoPublish": true
}
Facebook Page → Photo
{
"resource": "facebook",
"operation": "publishFbPhoto",
"pageId": "112233445566",
"imageUrl": "https://example.com/photo.jpg",
"caption": "FB photo caption"
}
Threads → Image
{
"resource": "threads",
"operation": "threadsPublishImage",
"thUserId": "987654321",
"imageUrl": "https://example.com/thread.jpg",
"text": "Threads image caption",
"altText": "Alt text for accessibility"
}
IDs are required per platform:
igUserId
pageId
thUserId
Skip Missing is your friend during setup—flip it off for stricter validation later.
Carousels: provide 2–10 items (IG) or 2–20 (Threads). The Publisher node will also poll children first for IG.
Meta Publisher node: in JSON mode it expects platform
internally, but we accept resource
and normalize it—your Utils output uses resource
as shown here (works with our Publisher).
Permalinks/insights: use a downstream HTTP Request or an enhanced Publisher to fetch them after publish.
Meta Publisher Utils (outputs { data: [...] }
)
Meta Publisher
From JSON Property
data
Optional: add If / Switch nodes to route successes vs errors (use status
, published
, etc.).
With this utility in front of your Publisher, you can define one compact set of inputs and instantly generate all the platform-specific jobs your workflow needs.
This repo uses the same conventions as the n8n node starter:
dist/
build
, lint
, lintfix
Typical loop:
npm i
npm run dev # tsc --watch
# In another terminal, run n8n and test
Refer to n8n’s “Using this starter” steps (generate repo, install deps, lint, test locally, publish) for overall workflow.
n8n documents how to run your node locally; follow those instructions to link your development build and iterate quickly.
Issues and PRs are welcome! Please:
npm run lint
/ npm run lintfix
)MIT — same as the official starter.
graph.threads.net
) under the Meta umbrella; this node handles it internally — you just choose Threads in the UI.FAQs
Publish to Instagram, Facebook Pages, and Threads (images, videos, reels, stories, carousels) via Meta Graph APIs.
The npm package n8n-nodes-meta-publisher receives a total of 207 weekly downloads. As such, n8n-nodes-meta-publisher popularity was classified as not popular.
We found that n8n-nodes-meta-publisher demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
Security News
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.
Product
Socket’s new Pull Request Stories give security teams clear visibility into dependency risks and outcomes across scanned pull requests.