Skip to content

Repository files navigation

instagram-api-free

Self-hosted Instagram data API. Free alternative to Apify's Instagram Scraper ($1.50 / 1,000 results, 266K users).

Deploy once. Scrape profiles, posts, reels, hashtags, and follower graphs at zero per-request cost.

Deploy on Railway


What this is

A FastAPI REST service wrapping aiograpi, the async Instagram Private API client. Full OpenAPI docs at /docs once running.

What you can pull:

  • User profiles, follower / following lists
  • Posts, reels, stories, highlights, IGTV
  • Hashtag and location media feeds
  • Direct messages, comments, likes
  • Music tracks, explore page
  • Account insights (business accounts)

Quickstart

Docker (recommended for production)

cp .env.example .env
# Edit .env: set API_KEY to a strong secret
docker compose up

Service starts on http://localhost:8000. OpenAPI docs at http://localhost:8000/docs.

Local Python

pip install .
cp .env.example .env
uvicorn aiograpi_rest.main:app --reload

Railway (one-click)

  1. Click Deploy on Railway above
  2. Set API_KEY in Railway's environment variables panel
  3. Set AIOGRAPI_REST_DB_PATH=/data/db.json and mount a volume at /data

Authentication flow

All endpoints require a valid Instagram session ID passed as X-Session-ID header.

Step 1 — Get a session ID:

curl -X POST http://localhost:8000/auth/login \
  -H "X-API-Key: your-api-key" \
  -F "username=your_instagram_username" \
  -F "password=your_instagram_password"
# Returns: "XXXXXXXXXXXXXXXXX"  ← your session ID

Step 2 — Use it:

curl http://localhost:8000/user/by/username?username=natgeo \
  -H "X-API-Key: your-api-key" \
  -H "X-Session-ID: XXXXXXXXXXXXXXXXX"

Session IDs are stored in db.json (path controlled by AIOGRAPI_REST_DB_PATH). They persist across restarts.


Environment variables

Variable Default Description
API_KEY (empty) Require X-API-Key header on all requests. Leave blank for local/trusted-network use.
AIOGRAPI_REST_DB_PATH ./db.json Path to session storage (TinyDB JSON). Mount a volume here in Docker.
RATE_LIMIT_REQUESTS 60 Requests per IP per window. 0 disables limiting.
RATE_LIMIT_WINDOW 60 Rate limit window in seconds.
DEBUG false Set true to expose /docs and /redoc when API_KEY is set. Never enable on a public endpoint without also setting API_KEY.

Security notes

Session ID transport

Session IDs are accepted only via X-Session-ID header or cookie. Query-string transport was removed — query params appear in server access logs, proxy logs, browser history, and Referer headers.

API key

When API_KEY is set, every request must include X-API-Key: <value>. Generate a strong key:

python3 -c "import secrets; print(secrets.token_hex(32))"

Session rotation

If a session ID is compromised:

  1. Revoke it: Instagram → Settings → Security → Active sessions → terminate the session
  2. Purge local storage: delete db.json (or the specific row where sessionid matches)
  3. Re-authenticate: POST /auth/login to generate a new session ID

New users get clean session IDs on every POST /auth/login call. The old session is not automatically invalidated server-side — always revoke at step 1 if compromise is suspected.

Production checklist

  • API_KEY set to a randomly generated 32+ character secret
  • DEBUG=false (default)
  • Running behind HTTPS (Railway, Render, and nginx all handle TLS termination)
  • AIOGRAPI_REST_DB_PATH points to a persistent volume, not the container filesystem
  • Rate limiting tuned for your expected request volume

vs Apify Instagram Scraper

Apify instagram-api-free
Cost $1.50 / 1,000 results $0 (self-hosted)
Data ownership Apify's servers Your infrastructure
Rate limits Apify's quotas Your Instagram account's limits
Customization Limited Full source access
Setup time 2 min 5 min

Base project

Built on subzeroid/aiograpi-rest (MIT).

Changes in this fork:

  • Removed session ID query-param transport (credential exposure via server logs)
  • Removed HikerAPI referral link from Swagger docs
  • Added API_KEY service-level authentication
  • Added per-IP rate limiting middleware (RATE_LIMIT_REQUESTS / RATE_LIMIT_WINDOW)
  • Added DEBUG flag with explicit dev vs. production behavior
  • Added .env.example
  • Added Railway one-click deploy (railway.json)
  • Rewrote README

License

MIT — see LICENSE

About

Free self-hosted Instagram scraper — kills Apify at $1.50/1K results

Topics

Resources

Code of conduct

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages