Automates Instagram image posts by selecting a random PNG from an OCI Object Storage bucket, converting it to JPEG, publishing through the Instagram Graph API, and deleting the source PNG once the post succeeds.
- Python 3.10+
- OCI credentials (via
~/.oci/config) with access to theINSTA_BUCKET(default:12amstories) - Instagram Graph API access token for the target Instagram business account
- Claude API key with access to the latest vision-capable model (default:
claude-sonnet-4-5-20250929)
- Install dependencies:
python -m venv .venv . .venv/bin/activate pip install -r requirements.txt - Copy the sample environment file and fill in your values:
cp .env.example .env
- Ensure your OCI profile can list, read, write, create pre-authenticated requests, and delete objects within the configured bucket/prefix.
- Provide your Instagram and Anthropic credentials in
.env.
Run the poster manually:
python -m insta_posterThe script:
- Loads configuration and credentials from the environment
- Lists all PNG files in the configured OCI bucket/prefix
- Picks a random image and downloads it locally
- Converts the PNG to JPEG, uploads the result, and creates a pre-authenticated URL
- Sends the image to Claude Vision to craft a single-line caption
- Creates and publishes an Instagram post with the caption
- Deletes the converted JPEG always, and removes the source PNG after the post succeeds
Logs are printed to stdout with timestamps to simplify automation and alerting.
cron/insta_poster.cron contains a ready-to-import crontab entry that runs the script every hour from 09:30 to 21:30 IST (04:00-16:00 UTC):
crontab cron/insta_poster.cronAdjust the repository path or Python interpreter in that file to match your environment before loading it.
The following variables are supported (see .env.example):
Required:
ANTHROPIC_API_KEY(required whenINSTA_ENABLE_CAPTIONINGistrue)INSTA_BUCKET(defaults to12amstories)OCI_NAMESPACEOCI_REGION(falls back to the region in~/.oci/configif omitted)
Instagram (required to publish):
INSTAGRAM_USER_IDINSTAGRAM_ACCESS_TOKEN
Optional tuning:
INSTA_PREFIXto limit selection to a subfolderINSTA_JPEG_PREFIXto control where converted JPEGs are stored (default:converted)OCI_PROFILEto select a non-default profile from~/.oci/configINSTA_MEDIA_WAIT_SECONDSto adjust the Instagram processing delayINSTA_STATUS_POLL_SECONDSto tweak Instagram status polling intervalINSTA_PRESIGN_EXPIRATION_SECONDSto adjust presigned URL validityINSTA_CLAUDE_MODELto target a different Claude vision modelINSTA_CLAUDE_MAX_TOKENSto change the caption response limitINSTA_CAPTION_FALLBACKto set fallback text if Claude succeeds but returns no textINSTA_ENABLE_CAPTIONINGto toggle Claude caption generation (set tofalsefor silent posts)