This workflow corresponds to n8n.io template #17589 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Schedule and publish Instagram posts at the best time with Rubinyun",
"nodes": [
{
"id": "sticky-1",
"name": "Read me first",
"type": "n8n-nodes-base.stickyNote",
"position": [
-40,
40
],
"parameters": {
"color": 3,
"width": 520,
"height": 1200,
"content": "## Schedule and publish Instagram posts at the best time\n\n**Who's it for**\n\nAnyone automating Instagram from n8n who needs a post to go out at a chosen time, including when their own machine is off. Images, carousels, reels and stories, on Instagram Business or Creator accounts.\n\n**How it works**\n\nThe Instagram API publishes immediately: there is no \"publish on Thursday at 6pm\", so something has to be awake at that minute to fire the call. This workflow hands that job to Rubinyun, which holds the queue and publishes for you.\n\n1. **Get the best time to post** returns the hour that performed best on your own account, worked out from your published posts. It also steps around the times you already have queued, so running this several times does not stack posts on the same minute.\n2. **Schedule the Instagram post** puts the post in the queue at that time.\n\n**How to set up**\n\n1. Create an account on chrononyte.com/rubinyun and connect Instagram once, there. Your Meta token never touches n8n.\n2. Open **API Keys** and copy your key and secret.\n3. In n8n add a **Header Auth** credential: name `Authorization`, value `Key YOUR_KEY:YOUR_SECRET`. Select it in both HTTP nodes.\n4. Put your own image URL and caption in *Schedule the Instagram post*.\n\n**Requirements**\n\nAn Instagram Business or Creator account linked to a Facebook Page, and a Rubinyun account. Free posts are included every month.\n\n**How to customize**\n\nChange `type` to `carousel`, `reel` or `story`. Add `channel` to publish on a second profile (`action=channels` lists them). No public URL for your media? Enable *Optional: upload a media file*: it takes binary data and answers with a public URL to use as the image URL.\n"
},
"typeVersion": 1
},
{
"id": "trigger-1",
"name": "Run manually to test",
"type": "n8n-nodes-base.manualTrigger",
"position": [
620,
300
],
"parameters": {},
"typeVersion": 1
},
{
"id": "http-besttime",
"name": "Get the best time to post",
"type": "n8n-nodes-base.httpRequest",
"notes": "Asks Rubinyun when to publish, from the engagement history of your own account.\n\nRun this flow several times in a row and you get different times: the answer steps around the posts already queued on that channel, so a loop does not pile everything onto the same minute. 'busy_skipped' in the response counts the slots it passed over.\n\nYou keep the last word: node 2 accepts any 'scheduled_at' you put there.",
"position": [
860,
300
],
"parameters": {
"url": "https://www.chrononyte.com/rubinyun/api.php",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "action",
"value": "besttime"
},
{
"name": "when",
"value": "tomorrow"
}
]
}
},
"notesInFlow": false,
"typeVersion": 4.2
},
{
"id": "http-add",
"name": "Schedule the Instagram post",
"type": "n8n-nodes-base.httpRequest",
"position": [
1100,
300
],
"parameters": {
"url": "https://www.chrononyte.com/rubinyun/api.php",
"method": "POST",
"options": {},
"sendBody": true,
"sendQuery": true,
"contentType": "form-urlencoded",
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "type",
"value": "image"
},
{
"name": "image_url",
"value": "https://www.chrononyte.com/assets/demo/rubinyun-demo.jpg"
},
{
"name": "caption",
"value": "Posted from n8n with Rubinyun"
},
{
"name": "scheduled_at",
"value": "={{ $json.slot.at }}"
},
{
"name": "channel",
"value": ""
}
]
},
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "action",
"value": "add"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "http-upload",
"name": "Optional: upload a media file",
"type": "n8n-nodes-base.httpRequest",
"notes": "Spare part, off by default and wired to nothing: enable it only if you have a FILE and no public URL for it.\n\nTo use it: connect a node that outputs the file as binary data (HTTP Request downloading it, Google Drive, your AI generator...) into this node, select the same Header Auth credential, and enable it. It answers {\"ok\":true,\"url\":\"...\"}, so in 'Schedule the Instagram post' set image_url to the expression {{ $json.url }}.\n\nField 'image' takes jpg, png, mp4 and mov (yes, 'image' for videos too). 'inputDataFieldName' is the name of the binary property coming in: n8n usually calls it 'data'.\n\nRubinyun keeps the file only as long as it takes to publish, then deletes it; files never attached to a post expire after 14 days. Parking is a pool per account, the TOTAL you can have parked at once: 200 MB on Free and packs, 2 GB with the \u20ac9 subscription, 5 GB with Unlimited. The reply includes parking.used_bytes and parking.limit_bytes so the workflow can check before hitting parking_full. Per file: images up to 8 MB, videos up to 100 MB. Channel keys work here too, and the file lands in that channel's own folder.",
"disabled": true,
"position": [
860,
560
],
"parameters": {
"url": "https://www.chrononyte.com/rubinyun/upload.php",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "multipart-form-data",
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "image",
"parameterType": "formBinaryData",
"inputDataFieldName": "data"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"notesInFlow": false,
"typeVersion": 4.2
},
{
"id": "sticky-upload-note",
"name": "About the optional upload",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
760
],
"parameters": {
"color": 7,
"width": 460,
"height": 300,
"content": "### Optional: you have a FILE, not a URL\n\nInstagram downloads the media from a public address, so a file on your disk cannot\nbe published as it is. Feed this node your file as binary data and enable it: it\nanswers with a public URL to put in the node on the right.\n\nThe file is deleted the moment the post is published, and expires on its own if it\nnever is: it is parking, not hosting."
},
"typeVersion": 1
}
],
"settings": {
"executionOrder": "v1"
},
"connections": {
"Run manually to test": {
"main": [
[
{
"node": "Get the best time to post",
"type": "main",
"index": 0
}
]
]
},
"Get the best time to post": {
"main": [
[
{
"node": "Schedule the Instagram post",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow uses Rubinyun via HTTP requests to pick an optimal posting time based on your Instagram account’s engagement history, then queues an Instagram post (image by default) to be published at that scheduled time. Runs when you manually execute the workflow. Calls the…
Source: https://n8n.io/workflows/17589/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
The Recap AI - Twitter Scraping. Uses formTrigger, httpRequest, googleSheets. Event-driven trigger; 13 nodes.
This workflow lets you post images to X (Twitter) by uploading binary image files obtained from any source, not just Google Drive. Whether you’re fetching images stored on Google Drive or working with
Who is this for? This template is perfect for sales teams, recruiters, marketing professionals, and business development specialists who need to gather comprehensive LinkedIn profile data at scale. Id
This workflow demonstrates the use of the HTTP Request node to upload binary files for form-data-multipart type. This example workflow updates the Twitter banner.
Manual Linkedin. Uses manualTrigger, httpRequest, linkedIn. Event-driven trigger; 3 nodes.