Instagram’s official Graph API requires the account owner to authenticate your app. If you need public data — follower count, bio, recent posts, engagement metrics — for accounts you don’t own, you need a third-party data API.
This tutorial uses the GramScraper API to fetch profile data, recent posts, and calculate basic metrics. Full working code in both Node.js and Python.
Setup
Sign up at gramscraper.com for 100 free credits (no credit card required). Grab your API key from the dashboard.
The API base URL is https://gramscraper.com/api/instagram/v1/. All requests need your API key in the x-api-key header.
Fetch a Profile
Python
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://gramscraper.com/api/instagram/v1"
def get_profile(username):
r = requests.get(
f"{BASE}/user/by/username",
params={"username": username},
headers={"x-api-key": API_KEY},
)
r.raise_for_status()
return r.json()
profile = get_profile("natgeo")
print(f"@{profile['username']}")
print(f"Followers: {profile['follower_count']:,}")
print(f"Following: {profile['following_count']:,}")
print(f"Posts: {profile['media_count']:,}")
print(f"Bio: {profile['biography']}")
print(f"Verified: {profile['is_verified']}")Node.js
const API_KEY = "YOUR_API_KEY";
const BASE = "https://gramscraper.com/api/instagram/v1";
async function getProfile(username) {
const url = `${BASE}/user/by/username?username=${username}`;
const res = await fetch(url, {
headers: { "x-api-key": API_KEY },
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
const profile = await getProfile("natgeo");
console.log(`@${profile.username}`);
console.log(`Followers: ${profile.follower_count.toLocaleString()}`);
console.log(`Following: ${profile.following_count.toLocaleString()}`);
console.log(`Posts: ${profile.media_count.toLocaleString()}`);
console.log(`Bio: ${profile.biography}`);
console.log(`Verified: ${profile.is_verified}`);Both return the same data. Node.js 18+ includes fetch natively — no dependencies needed.
Fetch Recent Posts
Once you have the profile, grab the user ID to fetch their posts:
Python
def get_posts(user_id, count=12):
r = requests.get(
f"{BASE}/user/posts",
params={"user_id": user_id, "count": count},
headers={"x-api-key": API_KEY},
)
r.raise_for_status()
return r.json()
user_id = profile["pk"]
posts = get_posts(user_id)
for post in posts.get("items", [])[:5]:
print(f"\n--- Post {post.get('code', '?')} ---")
print(f" Likes: {post.get('like_count', 0):,}")
print(f" Comments: {post.get('comment_count', 0):,}")
caption = post.get("caption", {})
if caption:
print(f" Caption: {caption.get('text', '')[:100]}...")Node.js
async function getPosts(userId, count = 12) {
const url = `${BASE}/user/posts?user_id=${userId}&count=${count}`;
const res = await fetch(url, {
headers: { "x-api-key": API_KEY },
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
const posts = await getPosts(profile.pk);
for (const post of (posts.items || []).slice(0, 5)) {
console.log(`\n--- Post ${post.code || "?"} ---`);
console.log(` Likes: ${(post.like_count || 0).toLocaleString()}`);
console.log(` Comments: ${(post.comment_count || 0).toLocaleString()}`);
console.log(` Caption: ${(post.caption?.text || "").slice(0, 100)}...`);
}Calculate Engagement Rate
With profile and post data, calculate engagement:
followers = profile["follower_count"]
items = posts.get("items", [])
if followers > 0 and items:
total_engagement = sum(
p.get("like_count", 0) + p.get("comment_count", 0)
for p in items
)
avg_engagement = total_engagement / len(items)
rate = (avg_engagement / followers) * 100
print(f"\nEngagement rate: {rate:.3f}%")
print(f"Based on {len(items)} recent posts")For a more detailed engagement script, see the engagement calculator tutorial.
Check if a Username Exists
Quick utility:
def username_exists(username):
try:
get_profile(username)
return True
except requests.HTTPError as e:
if e.response.status_code == 404:
return False
raise
print(username_exists("natgeo")) # True
print(username_exists("xyzzy_fake_99")) # FalseCredit Costs
Each API call costs 1 credit. The examples above use 2 credits total (1 profile + 1 posts). With the free 100 credits, you can run this 50 times before needing a paid plan.
The Standard plan at $29 gives you 15,400 credits. Credits don’t expire, so unused ones roll over indefinitely.
What Else Can You Fetch?
Beyond profiles and posts:
- Stories and Reels — active stories, reel data
- Comments — comments on any public post
- Hashtag data — top posts, post counts
- Location data — posts tagged at a location
- Search — users, hashtags, locations
- Media download — direct URLs for posts, stories, reels
Full endpoint list: API documentation. Test any endpoint interactively: playground.
Test GramScraper with 100 free credits
Use real public Instagram inputs, inspect the response, and estimate your endpoint mix before buying a pack.
Get an API keyOr review all GramScraper packs and the API documentation.