How I Connected Instagram and Threads to My Bot — Step by Step, No Magic
April 20, 2026
Two evenings, one Python file, and the bot posts Reels, Stories, and Threads on its own. Nothing complicated, as long as you don’t try to push through third-party schedulers.
Dima asked today: “how did you connect Instagram and Threads?” That matters because for most people that’s the main barrier — it feels like you need some kind of magic, API keys from Zuckerberg personally, and a week of wrestling with Meta documentation.
Actually — no. Two evenings and it all works. Here’s how.
Up front
I connected directly through the official Meta APIs. Not through SMMplanner, Postmypost, Buffer, or other schedulers. Third-party services are fine if you just want a more convenient way to schedule posts by hand — but if you have a bot that decides on its own what to post, when, and then reads the reaction — only the API. Everything below is about the API approach.
What you need out of the box
Before diving into code — check five things:
1. Instagram Business or Creator account. A regular personal one won’t do. Switching is free, done in settings with one click. Doesn’t take anything away.
2. A Facebook page linked to the Instagram account. Sounds archaic, but Meta is built that way: Instagram lives via a Facebook Page. You create an empty page, link it — you don’t have to post to it.
3. An app on Meta for Developers. Go to developers.facebook.com, create an App (Business type), get the App ID and Secret. Free, 5 minutes.
4. Long-lived Access Token. A regular token lives 1 hour, that’s useless. You need a long-lived one — it lives 60 days and renews. Obtained via Graph API Explorer + exchanging short for long.
5. Your account ID (Instagram and Threads separately). Just a number like 17841472854897166. Obtained with one API request once you have a token.
That’s it. Without these five things, neither side of the API will let you post anything.
Instagram — 6 steps
Step 1. On developers.facebook.com → My Apps → Create App → Business. Save the App ID and Secret.
Step 2. In the App settings add two products:
- Instagram Graph API (to post)
- Facebook Login for Business (to get a token)
Step 3. In Graph API Explorer pick your App, Generate Access Token, give the rights: instagram_basic, instagram_content_publish, pages_read_engagement, pages_show_list, business_management.
Step 4. Exchange the short token for long-lived in one request:
GET https://graph.facebook.com/v21.0/oauth/access_token
?grant_type=fb_exchange_token
&client_id=APP_ID
&client_secret=APP_SECRET
&fb_exchange_token=SHORT_TOKEN
The output — a 60-day token. Save it to .env.
Step 5. Find out your Instagram User ID:
GET https://graph.facebook.com/v21.0/me/accounts
?access_token=LONG_TOKEN
Returns a list of your Facebook Pages, each with the linked Instagram ID visible. Save it.
Step 6. Two-step publishing. Here’s the important thing people often trip over: you can’t just post. The API works like this:
- Create a media container — say “here’s a video URL, here’s the caption”
- Wait for the container to be processed (10 seconds — 2 minutes, polling status every 5–10 seconds)
- Send the command “publish this container”
Another important point: the Instagram API doesn’t accept files directly in the POST. It accepts a URL where the file sits on the internet. In my case files fly out to catbox.moe (a free anonymous file host), the direct link comes back, and that’s what I feed to the API. All integrations work this way.
Supported: Reels (video), Stories (video or photo), regular post (photo / carousel up to 10 photos).
Threads — same steps, separate API
Good news: Threads has a separate API (graph.threads.net), but the logic is one-to-one. If you’ve conquered Instagram — Threads is one extra evening.
Step 1. In the same Meta App add the Threads API product.
Step 2. In Graph API Explorer generate a token with rights: threads_basic, threads_content_publish, threads_manage_replies, threads_read_replies.
Step 3. Exchange for long-lived via the same fb_exchange_token.
Step 4. Find out your Threads User ID:
GET https://graph.threads.net/v1.0/me
?fields=id,username
&access_token=THREADS_TOKEN
Step 5. Same two-step publishing: /threads → polling → /threads_publish. Supported: text, image, video, carousel.
Bonus: in Threads you can post pure text without media. In Instagram you can’t.
The main Threads quirk
Threads has a nasty thing few people write about: if there’s a link in the main post — reach gets cut by about three times. Not the API, but the algorithm of the social network itself.
The solution I arrived at and that works:
- Publish the post without a link
- After 90 minutes — automatically send your own reply under that post with the link
The algorithm has already pushed the main post, the link in a reply doesn’t cut reach, the clicks work. I have a separate script for this + a queue of delayed replies in JSON, runs every 30 minutes via launchd.
If you’re going to do this — plan this logic in from the start. Otherwise in a month you’ll see a reach drop and won’t understand why.
Rakes I stepped on
Rake 1. The token. Meta promises that long-lived can be renewed a week before expiration. In practice — better to rotate every 30 days quietly with a script. Miss it — wake up to find that all the day’s posts went out as 401. Unpleasant.
Rake 2. The media file has to be on the internet. Not in memory, not in base64 — a URL with a direct link. I use catbox.moe. Any host with direct delivery works.
Rake 3. Container polling. Didn’t wait for FINISHED — went to publish — got an error. Looped without a timeout — the bot can die on a broken video. I have 30 attempts at 10 seconds, then “forget it” and a log to errors.
Rake 4. Reels requirements. Instagram has a strict video format: h264 / mp4, 1080×1920, up to 30fps, up to 90 seconds. If it doesn’t fit — ERROR with no clear explanation. Run it through ffmpeg, bring it to standard.
Rake 5. Meta policy. Once every 2–4 months they change something: API version, review process, scope of rights. Subscribe to their Developer Newsletter, check the changelog once a month.
Rake 6. Rate limits. Instagram has 50 posts a day per account. Huge cushion for a human, but if you run aggressive automation — don’t push out of bounds.
What it costs
- Meta Developer App — free.
- Instagram/Threads Business account — free.
- File hosting (catbox.moe) — free.
- A server for the script — mine runs on a regular Mac mini via LaunchAgent. Can be on Hetzner for 4 euros a month if no Mac.
In total: zero rubles and 2–3 evenings to figure it out (if it’s your first time).
Working script
I put up a clean minimal example as a gist — Instagram and Threads only, without my home wiring (mine also has VK, Pinterest, Telegram on top). The file is ~280 lines, one dependency (requests).
📎 Script: gist.github.com/magic-dev-kz/meta_publisher.py
Take it, open it in your own Claude Code — and say “read this and adapt it to my needs.” It’ll figure it out, plug it into your bot.
Bottom line
Connecting Instagram and Threads isn’t magic. It’s five checkboxes in settings, one token exchange, two nights of careful reading of Meta’s docs, and one Python file.
It’s worth doing yourself if you have a bot or a pipeline — something that decides on its own when and what to post. If you just want a more convenient way to plan by hand — take SMMplanner, don’t suffer.
The future isn’t in posting nicely by hand. It’s in your bot doing it on its own while you’re busy with something else.
Questions and showing me your first working post — DM me at @magic4e. Subscribe to @mdkguru — that’s where I show how I’m building my team of AI agents and what it’s turning into.
Liked the article?
@mdkguru on Telegram →