Install
openclaw skills install instagram-publish-tutorUse when publishing images to Instagram via the Graph API from a Creator or Business account. Triggers when the user wants to automate Instagram posting, push an image with caption to their account, set up Instagram API access for the first time, or troubleshoot Instagram Graph API errors like "Media download has failed" or "Unsupported post request". Assumes one-time Meta App setup is complete and an Access Token is available.
openclaw skills install instagram-publish-tutorPublish images to Instagram through Meta's Graph API. Part 1 is one-time manual setup (browser clicks); Part 2 is the repeatable automated publish (this skill does it for you).
# 1. Put credentials in .env (one time)
cp .env.example .env
# edit .env with ACCESS_TOKEN (and optionally IG_USER_ID)
# 2. Publish
python3 scripts/publish.py \
--image-url "https://example.com/photo.jpg" \
--caption "Hello from Instagram API"
The script prints the new post ID on success. Done.
These steps cannot be automated — they require human logins, email verification, and Meta's UI. Do them once, save the resulting ACCESS_TOKEN, and you never need to touch Meta's dashboard again unless permissions change.
Visit https://www.instagram.com/accounts/professional_account_settings/ and follow:
Settings
↓
Account Type
↓
Switch to Professional Account
↓
Creator
Visit https://developers.facebook.com/ and sign in with your Facebook account, then:
Get Started
↓
Verify Email
↓
Accept Terms
Visit https://developers.facebook.com/apps/:
Create App
↓
Use cases: Manage messaging & content on Instagram
↓
Do NOT connect a Business portfolio
⚠️ Skipping the Business portfolio avoids the "insufficient developer permissions" error later.
In App settings → Basic:
Use cases → Customize
↓
Left sidebar: API setup with Instagram login
↓
Add required messaging permissions
↓
Add account → authorize your Instagram account
↓
Generate token
↓
Check "I understand" → copy the token
The token starts with IGAA.... Save it to .env (next section).
| Field | Example | Lives in |
|---|---|---|
ACCESS_TOKEN | IGAAxxxxx... | .env |
IG_USER_ID | 2700xxxxxx | .env (optional — script can auto-fetch) |
USERNAME | xxxxx | reference only |
⚠️ Never commit
.envto git. The token is the only thing that authenticates posts on your behalf.
The three Graph API calls below are bundled in scripts/publish.py. You run one command; the script runs all three.
[1] Validate token → GET /me?fields=id,username
↓
[2] Create container → POST /{ig_user_id}/media (image_url + caption)
↓
[3] Publish → POST /{ig_user_id}/media_publish (creation_id)
.envcp .env.example .env
.env contents:
ACCESS_TOKEN=IGAAxxxxxxxxxxxxxxxxxxxx
IG_USER_ID=2700xxxxxxxx # optional — auto-detected if missing
The script reads .env from the skill directory. If you run it from elsewhere, pass --env /path/to/.env.
python3 scripts/publish.py \
--image-url "https://example.com/photo.jpg" \
--caption "Hello from Instagram API"
Optional flags:
| Flag | Default | Notes |
|---|---|---|
--image-url URL | required | Must be publicly reachable by Meta's servers |
--caption TEXT | empty | Instagram's caption, with hashtags and mentions |
--env PATH | ./.env | Path to a .env file |
--api-version | v24.0 | Graph API version |
--dry-run | off | Validate token and build the container, but skip the final publish |
Successful output:
✓ Token valid — user: xxxxx (id: 2700xxxxxx)
✓ Container created: xxxxx
✓ Published: xxxxx
https://www.instagram.com/p/xxxxxxxxx
{"error": {"message": "Media download has failed"}}
Meta's servers cannot reach your image_url. Fix:
localhost, 127.0.0.1, and private network IPs{"error": {"message": "Unsupported post request"}}
Almost always a token-permission issue. Fix:
instagram_content_publish and instagram_basic are grantedACCESS_TOKEN in .envLong-lived tokens still expire (default ~60 days). If /me returns an auth error, regenerate the token in the App dashboard and update .env.
instagram-publish/
├── SKILL.md # this file
├── .env.example # template for ACCESS_TOKEN and IG_USER_ID
├── .gitignore # keeps .env out of git
└── scripts/
└── publish.py # the three-step publisher