Python Instagram API options, with the code for each
Published
If you are looking for a Python Instagram API, there is no single library that covers the job — there are four different paths, and the one you want is decided by whether you need a login, a date range, or a bill you can predict. Meta publishes an official API that is free and very narrow. A well-known open-source Python library drives Instagram's private endpoints from your own account. Paid REST APIs sell requests. And a hosted actor runs the scrape for you and hands Python a dataset. This page shows the code for each, says what each charges as of September 2026, and — because this site publishes one of them — says plainly where the other three are the better answer.
Every figure and quote below was read off the vendor's own page in September 2026, and each page is named so you can check it before you plan a budget around it.
The four Python Instagram API paths, side by side
| Path | What you install | Login needed | Billing unit | Best for |
|---|---|---|---|---|
| Meta Graph API | requests | a Meta business token | free, inside hard limits | watching under 30 fixed hashtags, last 24 hours |
| instagrapi | instagrapi | your own Instagram account | free library, your own risk | flexible research, tolerant of breakage |
| HikerAPI | requests | none | per request | many endpoints, no cookie handling |
| A hosted actor | apify-client | your own session cookie, for this actor | per delivered post | one hashtag, on a schedule, fixed budget |
The split that matters is not "official vs unofficial" — it is who carries the session. Two of these paths ask your code to hold an Instagram login; two do not. If your security review forbids storing a session cookie, that single line removes half the table before price is discussed at all.
Meta's official Python Instagram API, and where it stops
The official path is plain HTTP, so requests is the whole dependency. Two calls: resolve the hashtag to an ID, then read its media edge.
import requests
BASE = "https://graph.facebook.com/v21.0"
params = {"user_id": USER_ID, "q": "coffee", "access_token": TOKEN}
tag = requests.get(f"{BASE}/ig_hashtag_search", params=params).json()
tag_id = tag["data"][0]["id"]
media = requests.get(
f"{BASE}/{tag_id}/recent_media",
params={
"user_id": USER_ID,
"fields": "id,caption,like_count,comments_count,timestamp,permalink",
"access_token": TOKEN,
},
).json()
Meta's own reference page for IG Hashtag Search states the limits in as many words:
"You can query a maximum of 30 unique hashtags within a 7 day period."
The same reference notes that hashtag IDs are static and global — the ID for #bluebottle is the same for every app and every user — which is worth caching, because resolving an ID spends from the same 30-hashtag budget as reading posts does.
The recent_media edge is narrower still: public photos and videos only, published in the 24 hours before your query. So:
- No backfill. A hashtag you thought of today has no history you can read.
- No sweep. Thirty unique hashtags a week does not cover a campaign audit.
- An app review stands in front of it. Instagram Public Content Access is applied for against a stated business use case, with a Facebook Page and a connected professional account behind it.
If your job fits inside those limits, stop here — free and first-party beats every rate on this page. Most hashtag jobs do not fit, which is why the rest of this page exists.
instagrapi: the Python library that drives the private API
instagrapi is the library most Python searches land on, and it works differently from everything else here: it signs in as you and calls the endpoints the Instagram app itself uses.
from instagrapi import Client
cl = Client()
cl.login(USERNAME, PASSWORD)
medias = cl.hashtag_medias_recent("coffee", amount=200)
Its GitHub page describes it, as of September 2026, as "The fastest and powerful Python library for Instagram Private API 2026 with HikerAPI SaaS" — and that last clause is the honest part of the picture: the same project publishes a paid hosted API alongside the free library. Read that as the shape of the trade rather than as a criticism. The library is free, gives you the widest surface of any option here, and costs you:
- Your own account's exposure. Automated reads from a residential-looking client are what rate limits and challenge screens exist for.
- Maintenance. Private endpoints change without notice, and your pipeline breaks on a Thursday with no status page to check.
- Nothing promises delivery. There is no meter, no dataset, no retry policy but the one you write.
Take this path when you are exploring, when you can babysit it, and when a broken run costs you an afternoon rather than a report.
HikerAPI: paying per request instead of holding a session
If you want the private-API surface without your code holding an Instagram login, a paid REST API is the straight swap. HikerAPI's pricing page, September 2026, is headed "Instagram API Pricing: $0.60 per 1,000 Requests" and states:
"Instagram API cost: $0.60 per 1,000 requests at volume, $1 per 1,000 on the popular plan. Pay per request, no subscription, no lock-in. 100 free requests."
Its FAQ on that page is specific about what counts: it charges for any successful response (including 400, 403 and 404), never charges for 50x errors, and says a balance never expires. A Hashtags API sits alongside its profile, posts, stories, followers, comments, locations and search endpoints. In Python it is just requests:
import requests
r = requests.get(
"https://api.hikerapi.com/v1/hashtag/medias/recent",
params={"name": "coffee"},
headers={"x-access-key": KEY},
)
What the pricing page does not publish is how many posts one request returns, and for a hashtag job that single unknown decides your bill. Price it with a small test run before you plan around it — a per-request rate means nothing until you know the rows per request.
A hosted actor: letting Python read a dataset instead of a feed
The fourth path moves the scraping out of your process entirely. You call a hosted actor, it walks the hashtag, and your Python reads the finished rows. That is what this site publishes, and it is deliberately narrow: one hashtag, an exact result limit, a real date filter, and billing only on rows actually delivered.
from apify_client import ApifyClient
client = ApifyClient(APIFY_TOKEN)
run = client.actor("tiraisoft/instagram-hashtag-scraper").call(run_input={
"hashtag": "coffee",
"resultsLimit": 500,
"onlyPostsNewerThan": "7 days",
"sessionCookie": "sessionid=...; csrftoken=...",
})
for post in client.dataset(run["defaultDatasetId"]).iterate_items():
print(post["timestamp"], post["likesCount"], post["url"])
The client is Apify's official apify-client package on PyPI; its documentation, September 2026, states that it requires Python 3.11 or higher and offers both synchronous and asynchronous interfaces with built-in retries and exponential backoff. pip install apify-client is the whole setup.
Three specifics decide whether this path fits your job:
resultsLimitis an exact ceiling, not a target. Ask for 500 and the run stops at 500.onlyPostsNewerThanstops the walk rather than filtering afterwards. Asking for seven days ends the run when the feed reaches that date, so a week of posts costs a week of rows — and there is anonlyPostsOlderThanbound too, so you can take a window out of the middle.- It runs on a session cookie from an account you control. You supply
sessionidandcsrftoken. This is the real trade and it belongs next to the price: if your policy forbids that, this option is off your list and HikerAPI or Meta's Graph API is the correct answer.
Billing is $0.0005 per delivered post on every plan, drawn from your Apify usage. A run that finds nothing delivers nothing and costs nothing, which is the difference that matters if you poll a quiet hashtag hourly.
Which one to pick
| If this describes you | Pick |
|---|---|
| Under 30 hashtags, only the last 24 hours, Meta app approved | Meta Graph API |
| Exploring, comfortable maintaining it, using your own account | instagrapi |
| Many different endpoints, no session in your code | HikerAPI |
| One hashtag, a date window, a row cap, a predictable bill | a hosted actor |
Two of these are free and two are metered, and the free ones are free in different ways. Meta's is free because it is narrow. instagrapi is free because the cost is borne by your account and your maintenance time. Neither is a bargain if the job needs backfill on a schedule; both are the right answer if it does not.
Wiring whichever you pick into Python
The migration between these is smaller than it looks, because they all end in the same place — a list of posts with a caption, a timestamp and engagement counts.
- Write down the query first: the hashtag, the date window, the row cap. If the window is longer than 24 hours, Meta's API was never going to answer it, and no amount of tuning changes that.
- Keep the official path for whatever it already covers. It is free; there is no reason to pay for a job it does.
- Normalise on your side, once. Give yourself one
Postdataclass and map each source into it — that is what makes swapping paths a one-file change later. - Decide the session question before the price question. It removes options faster than any number here.
- Measure one real run before you budget. Rows per request, posts per day on your hashtag, and how often the run finds nothing are the three numbers that decide the bill on any metered path.
If the job is one hashtag, on a schedule, with a hard budget, this site's actor does that and nothing else. If it is anything broader — many endpoints, many networks, or no session allowed — one of the other three is a better fit, and the Instagram hashtag API comparison prices those side by side in more detail.