import-pixelfed#
Import Instagram photos from a data export into Pixelfed via the Mastodon-compatible API.
Features#
- Parses Instagram data export JSON
- Imports posts in chronological order (oldest first)
- Strips GPS/location EXIF data from images before upload
- Prepends original post date to captions
- Supports multi-image carousel posts
- Photos only (skips videos and reels)
- Posts as unlisted visibility
- Progress tracking with resume capability
- Rate limiting to avoid server hammering
- Dry run mode for testing
Requirements#
- Python 3.12+
- uv package manager
- Instagram data export (request from Instagram settings)
- Pixelfed account with Personal Access Token
Installation#
git clone https://git.mauve.haus/mauvehed/import-pixelfed.git
cd import-pixelfed
uv sync
Configuration#
Copy the example environment file and fill in your values:
cp .env.example .env
Environment variables:
| Variable | Description | Default |
|---|---|---|
PIXELFED_HOST |
Your Pixelfed instance hostname | pixelfed.social |
ACCESS_TOKEN |
Personal Access Token from Pixelfed | (required) |
EXPORT_PATH |
Path to Instagram export folder | ./ig_export |
RATE_LIMIT_DELAY |
Seconds between posts | 5 |
DRY_RUN |
Set to 1 to test without uploading |
(unset) |
Getting a Pixelfed Access Token#
- Log into your Pixelfed instance
- Go to Settings > Applications > Personal Access Tokens
- Create a new token with
writescope - Copy the token to your
.envfile
Instagram Export Structure#
Place your Instagram data export in the ig_export/ directory:
ig_export/
├── your_instagram_activity/media/
│ └── posts_1.json # Posts metadata
└── media/
└── posts/YYYYMM/*.jpg # Post images
Usage#
Dry Run (recommended first)#
Test parsing without uploading:
DRY_RUN=1 uv run import_to_pixelfed.py
Run Import#
uv run import_to_pixelfed.py
The script will:
- Load posts from
posts_1.json - Sort by date (oldest first)
- Skip video posts
- Strip GPS data from images
- Upload media and create posts
- Save progress to
import_progress.json
Resuming Interrupted Imports#
The script automatically tracks progress. If interrupted, simply run it again and it will skip already-imported posts.
Caption Format#
Since the Mastodon API does not support backdating posts, the original date is prepended to each caption:
Originally posted: 2019-07-15
Beach day! #summer
Captions are truncated at 500 characters if needed.
Error Handling#
- Retries on rate limits (429) and server errors (500, 502, 503)
- Failed posts are logged to
import_failed.jsonfor manual review - Import can be resumed after fixing issues