Paste a public profile, post or reel. Web Unlocker returns the Instagram page with no login: a profile's exact follower count and 12 latest posts, a post's exact likes, comments and caption. $0.98 per 1,000 pages.
1,000 free requests · Pay only on success · 195+ countries · Claude ready
Instagram pages take 3 to 12 seconds. It is still working, no need to click again.
Ready for your own profiles? Get an API key or book a demo.
Tell us a little about your team and get:
Public pages, with no login and no Instagram account. Influencer platforms, brands, social listening tools and researchers read these four kinds of page, each billed as one page.










Want to try it yourself? Take your API key with 1,000 free requests.
Web Unlocker bills a profile page once, with its exact followers and 12 latest posts, at $0.98 per 1,000 pages. Instagram profile scrapers on Apify, Bright Data and ScrapeCreators charge more for the same profile.
Apify bills $2.60 per 1,000 profiles.
Here 1,000 cost $1.14.
Instagram sends about one profile page in seven back empty. Ask for it again at a fresh address and the data comes back: the price above counts those retries.
What 1,000 Instagram profiles cost
1,000 public profiles with followers and bio, at published prices
Gologin: $0.98 per 1,000 pages, plus one retry for about every seven profiles. Bright Data bills each record, $1.50 per 1,000. ScrapeCreators bills each request, $1.88 per 1,000 on its $47 plan. Apify's own Instagram profile scraper bills $2.60 per 1,000 profiles on the free plan.
Ready to run it on your own profiles? Get your API key and free requests.
Our Instagram scraping test: 20 profiles, 20 posts and 20 reels from their grids, and 10 hashtag pages, each asked for up to three times, the way the demo above does it. This is what came back, and how fast.
51 of 60 came back on the first try.
The other 9 on the second or third.
Instagram's own API, Apify's Instagram scrapers and Bright Data's Instagram Scraper API: what each bills for the same 1,000 profiles, and what it asks of you before you start.
| What it takes | ||||
|---|---|---|---|---|
| You pay for | A page | Free within limits | Each result | Each record |
| 1,000 profiles | $1.14 | Free | $2.60 | $1.50 |
| Personal accounts | Yes | No | Yes | Yes |
| Your own Instagram account | Not needed | Professional account | Not needed | Not needed |
| Free to start | 1,000 requests | With a Meta app | $5 a month | 5,000 a month |
| The whole page in HTML | Yes | No | No | No |
Scraping more than Instagram? Web Unlocker returns any page the same way, at the same price.
A profile page brings the 12 latest posts, and each post page brings its exact likes and comments. 13 pages, $0.0127, and you have the creator's real engagement, post by post.
Instagram rounds to 268M.
The scraper returns 268,157,304.
Instagram keeps a public page's data as JSON inside its HTML. Web Unlocker returns that HTML, and a few lines of code read the profile or the post out of it. The Profiles list tab is a small Instagram crawler: a list of accounts in, a CSV out.
Fill in the form above. The key arrives by email within one business day.
A profile for its followers and latest posts, a post or reel for its likes and comments.
Check that the page came with data, and ask again at a fresh address when Instagram sent an empty one.
pip install requestsGOLOGIN_SCRAPING_API_KEY=your_key python instagram_profile.pyhttps://parsing.webunlocker.gologin.com/v1/scrapeimport json
import os
import re
import time
import requests
username = "nasa"
def scrape(url, marker):
for attempt in range(3):
address = url if attempt == 0 else f"{url}?fresh={int(time.time())}"
response = requests.get(
"https://parsing.webunlocker.gologin.com/v1/scrape",
params={"url": address, "geo": "us", "format": "json"},
headers={"apikey": os.environ["GOLOGIN_SCRAPING_API_KEY"]},
timeout=90,
)
page = response.json().get("data", {}).get("html", "") if response.ok else ""
if marker in page:
return page
time.sleep(3)
raise RuntimeError("The page came back without data, try again later")
def blocks(page):
for block in re.findall(r'<script type="application/json"[^>]*>(.*?)</script>', page, re.S):
try:
yield json.loads(block)
except json.JSONDecodeError:
pass
def find(node, key):
if isinstance(node, dict):
for name, value in node.items():
if name == key:
yield value
yield from find(value, key)
elif isinstance(node, list):
for item in node:
yield from find(item, key)
data = list(blocks(scrape(f"https://www.instagram.com/{username}/", '"follower_count"')))
user = next(item for item in find(data, "xig_user_by_username") if "follower_count" in item)
posts = {}
for timeline in find(data, "polaris_ordered_timeline_connection"):
for edge in timeline["edges"]:
post = edge["node"]
reel = post.get("product_type") == "clips"
posts[post["code"]] = {
"url": f"https://www.instagram.com/{'reel' if reel else 'p'}/{post['code']}/",
"type": "reel" if reel else "post",
"caption": (post.get("caption") or {}).get("text", "").split("\n")[0],
"image": post.get("display_uri"),
}
profile = {
"username": user["username"],
"full_name": user["full_name"],
"biography": user["biography"],
"verified": user["is_verified"],
"followers": user["follower_count"],
"following": user["following_count"],
"latest_posts": list(posts.values())[:12],
}
print(json.dumps(profile, indent=2, ensure_ascii=False))
print(f"@{username}: {profile['followers']:,} followers, {len(profile['latest_posts'])} latest posts from one page")GOLOGIN_SCRAPING_API_KEY=your_key node instagram-engagement.mjshttps://parsing.webunlocker.gologin.com/v1/scrapeimport { writeFileSync } from 'node:fs';
const username = 'natgeo';
async function scrape(url, marker) {
for (let attempt = 1; attempt <= 3; attempt++) {
const address = attempt === 1 ? url : `${url}?fresh=${Date.now()}`;
const params = new URLSearchParams({ url: address, geo: 'us', format: 'json' });
const response = await fetch(`https://parsing.webunlocker.gologin.com/v1/scrape?${params}`, {
headers: { apikey: process.env.GOLOGIN_SCRAPING_API_KEY },
});
const page = response.ok ? (await response.json()).data?.html : '';
if (page?.includes(marker)) return page;
await new Promise((resolve) => setTimeout(resolve, 3000));
}
throw new Error(`${url} came back without data, try again later`);
}
function* find(node, test) {
if (Array.isArray(node)) for (const item of node) yield* find(item, test);
else if (node && typeof node === 'object') {
if (test(node)) yield node;
for (const value of Object.values(node)) yield* find(value, test);
}
}
const data = (page) =>
[...page.matchAll(/<script type="application\/json"[^>]*>([\s\S]*?)<\/script>/g)].flatMap(([, json]) => {
try {
return [JSON.parse(json)];
} catch {
return [];
}
});
const profile = data(await scrape(`https://www.instagram.com/${username}/`, '"follower_count"'));
const user = find(profile, (node) => typeof node.follower_count === 'number').next().value;
const codes = [...new Set([...find(profile, (node) => node.code && node.display_uri)].map((post) => post.code))].slice(0, 12);
const posts = [];
for (const code of codes) {
const page = data(await scrape(`https://www.instagram.com/p/${code}/`, '"like_count"'));
const post = find(page, (node) => typeof node.like_count === 'number' && node.code === code).next().value;
posts.push({ url: `https://www.instagram.com/p/${code}/`, date: new Date(post.taken_at * 1000).toISOString().slice(0, 10), likes: post.like_count, comments: post.comment_count });
}
const csv = ['url,date,likes,comments', ...posts.map((post) => `${post.url},${post.date},${post.likes},${post.comments}`)].join('\n');
writeFileSync(`${username}-posts.csv`, csv);
const average = posts.reduce((sum, post) => sum + post.likes + post.comments, 0) / posts.length;
console.table(posts);
console.log(`@${username}: ${user.follower_count.toLocaleString('en-US')} followers, ${Math.round(average).toLocaleString('en-US')} likes and comments a post`);
console.log(`Engagement rate ${((average / user.follower_count) * 100).toFixed(2)}% from ${posts.length + 1} pages: $${((posts.length + 1) * 0.00098).toFixed(4)} on the Growth plan`);GOLOGIN_SCRAPING_API_KEY=your_key node instagram-profiles.mjshttps://parsing.webunlocker.gologin.com/v1/scrapeimport { writeFileSync } from 'node:fs';
const usernames = ['nasa', 'natgeo', 'nike', 'spotify', 'starbucks', 'redbull'];
async function scrape(url) {
for (let attempt = 1; attempt <= 3; attempt++) {
const address = attempt === 1 ? url : `${url}?fresh=${Date.now()}`;
const params = new URLSearchParams({ url: address, geo: 'us', format: 'json' });
const response = await fetch(`https://parsing.webunlocker.gologin.com/v1/scrape?${params}`, {
headers: { apikey: process.env.GOLOGIN_SCRAPING_API_KEY },
});
const page = response.ok ? (await response.json()).data?.html : '';
if (page?.includes('"follower_count"')) return page;
await new Promise((resolve) => setTimeout(resolve, 3000));
}
return '';
}
const field = (page, name) => page.match(new RegExp(`"${name}":("(?:[^"\\\\]|\\\\.)*"|\\d+|true|false)`))?.[1];
const rows = [];
for (const username of usernames) {
const page = await scrape(`https://www.instagram.com/${username}/`);
rows.push({
username,
name: page && JSON.parse(field(page, 'full_name')),
verified: page && field(page, 'is_verified') === 'true',
followers: page && Number(field(page, 'follower_count')),
following: page && Number(field(page, 'following_count')),
posts: page.match(/([\d.,]+[KMB]?) Posts/)?.[1],
});
}
writeFileSync('profiles.csv', ['username,name,verified,followers,following,posts', ...rows.map((row) => Object.values(row).map((value) => JSON.stringify(value ?? '')).join(','))].join('\n'));
console.table(rows);
console.log(`${rows.length} profiles in ${rows.length} pages: $${(rows.length * 0.00098).toFixed(4)} on the Growth plan`);Ready to run it on your own profiles? Get your API key and free requests.
One account, one proxy network, one ecosystem. Pick the product the job needs.
Scraping more sites? See the Facebook, Google Play, Twitter (X), YouTube, Reddit and Google Maps scrapers, or every web scraping tool.
An Instagram scraper is a tool that reads public Instagram pages and turns them into data: a profile's followers, bio and latest posts, a post's likes, comments and caption. Gologin Web Unlocker is an Instagram scraper API: send it a page address and it returns the page with that data, at $0.98 per 1,000 pages.
Send the address of a public profile, post or reel to Web Unlocker. It returns the page as a logged-out visitor sees it, with the data Instagram keeps inside it as JSON: followers, posts, likes, comments and captions. The code above reads it in a few lines.
Send the profile address to Web Unlocker with the requests library and read the JSON from the page. The Python tab above is a complete script, tested on the live API: it prints the profile's followers, following, bio and 12 latest posts.
Only in part. Business Discovery in the Instagram API reads business and creator accounts, and only from your own professional account through a Meta app. Personal accounts are not covered, and hashtag search stops at 30 tags a week. The old Basic Display API ended on 4 December 2024.
Yes. Public profiles, posts, reels and a hashtag's popular page load without a login. Web Unlocker opens them as a logged-out visitor, so you need no Instagram account and put none of yours on the line. Private profiles stay closed: their posts are for approved followers only. TikTok works the same way: the TikTok scraper reads public profiles and videos with no login.
Instagram now and then sends a page with no data in it: about one profile page in seven in our test. The demo above and the code samples check for the data and ask again at a fresh address. Posts and reels came back on the first try 36 times in 40.
Not as a list: an account's list of followers opens only for logged-in users. The exact follower count is public, and Web Unlocker returns it with every profile.
The comment count, yes: every post and reel page carries the exact number. The comments themselves load for logged-in users, so Web Unlocker does not return them.
For many hashtags Instagram shows logged-out visitors a popular page with 12 top reels and their play counts, and Web Unlocker returns it. The full feed of a hashtag is for logged-in users.
Yes. Every post on a profile page and every post page comes with the links to its picture files, so your code can save them.
$0.98 per 1,000 pages, the same for every page: a profile with its 12 latest posts is one page, a post is one page. A request that fails costs nothing. Plans start at $49 a month for 50,000 requests.
Web Unlocker comes with 1,000 free requests, enough for 1,000 profiles or posts. Open-source tools like Instaloader and instagrapi are free: they run on your own servers, often ask for an Instagram login, and keeping them working as Instagram changes is up to you.
It depends on the job. The Instagram API is free for the business and creator accounts you can reach from your own. Apify and Bright Data sell ready rows and bill every result. Web Unlocker returns the whole public page at one price per page, on Instagram and on any other site.
Yes. Apify's Instagram profile scraper bills $2.60 per 1,000 profiles on its free plan. Web Unlocker returns the same public profile page with the exact follower count and 12 latest posts for $1.14 per 1,000 profiles, retries counted.
Profiles, posts and reels that load without a login are public pages. In Meta v. Bright Data, in January 2024, a US federal court found that Meta's terms do not bar logged-out scraping of public data. What you collect and how you use it is your call, so check it against the rules that apply to your project.
Tell us a little about your team and get: