Start free

How to scrape Instagram

Extract public Instagram profile and post metadata as typed JSON. Login-gated data is Enterprise only. Heavy anti-bot, SPA rendering, ToS-aware.

Site:
instagram.com
Difficulty:
Hard
Rendering:
Single-page app
Anti-bot:
managed anti-bot bypass layer (Cloudflare, DataDome, PerimeterX style protections handled for you), aggressive login wall after a handful of unauthenticated views, aggressive per-IP rate limiting and throttling applied to unauthenticated traffic, GraphQL response obfuscation and frequently rotated internal endpoints, device and behavioral fingerprinting on the web client

What you can extract from Instagram

These are the fields teams most often pull from instagram.com, and why a hand-written selector for each one tends to break over time.

Field Type Why selectors break
username string The handle is rendered by Instagram's React SPA into hashed, build-specific class names that rotate on every deploy, so a CSS selector pinned to today's div class silently returns null after the next frontend release.
fullName string Display names sit in the same obfuscated component tree as the username and bio, and Instagram frequently swaps the wrapping element between a header span and a heading tag, so a positional selector grabs the wrong text or nothing at all.
followerCount number Follower totals are shown abbreviated (12.3M) in the visible DOM while the exact integer lives only in an embedded GraphQL/JSON blob, so a CSS selector captures a lossy string you then have to parse and un-abbreviate by hand.
followingCount number This count shares an identical markup pattern with followers and posts in a three-item header list with no stable labels, so an index-based selector breaks the moment Instagram reorders or A/B tests that header row.
postCount number The post total is injected after hydration and is missing from the first server response, so a selector that runs before the SPA finishes mounting sees an empty node and a guessed scrape returns zero instead of the real value.
isVerified boolean Verification is conveyed only by a decorative SVG badge with no text and no stable aria attribute, so there is no reliable CSS selector for a true/false value without inferring presence of an icon whose class hash changes between builds.
externalUrl string Bio links are wrapped in an l.instagram.com redirect with tracking parameters and the real destination is encoded in a query string, so a selector reading the href returns the tracker rather than the actual URL the profile points to.
isPrivate boolean Privacy state is expressed as the absence of a grid plus a localized text notice, so a selector keyed to English copy fails entirely on non-English locales and cannot be trusted as a structured flag.

The schema-first approach

Instead of maintaining selectors, you hand Extracto a JSON schema describing the shape you want. Here is a schema that works for Instagram:

{
  "username": "string",
  "fullName": "string",
  "biography": "string",
  "followerCount": "number",
  "followingCount": "number",
  "postCount": "number",
  "isVerified": "boolean",
  "isPrivate": "boolean",
  "externalUrl": "string",
  "profilePicUrl": "string",
  "category": "string"
}
  1. 1

    Describe the Instagram fields you want

    Write a small JSON schema listing the fields to pull from instagram.com (for example username, fullName, followerCount). No CSS selectors or XPath needed.

  2. 2

    Send the URL and schema to Extracto

    POST the Instagram page URL and your schema to the Extracto API. Extracto renders the page in a real browser, handling JavaScript and dynamic content automatically.

  3. 3

    Get schema-validated JSON back

    Extracto returns JSON that matches your schema exactly, validated before it leaves the API, so your pipeline never receives broken or partial data.

Common pitfalls when scraping Instagram

Is it legal to scrape Instagram?

Instagram is one of the harder targets to scrape responsibly, and you should treat it as login-gated by default. Meta's Terms of Use prohibit automated collection of data without prior written permission, and instagram.com/robots.txt disallows most crawler paths while explicitly naming approved partners. Instagram routinely forces a sign-in wall after a small number of unauthenticated profile or post views, so even "public" pages are only briefly visible without an account. With Extracto you can reliably reach the small surface that remains public to logged-out visitors: top-level profile metadata and some post-level metadata rendered into the initial document. Anything behind login (full follower lists, private accounts, Stories, DMs, the logged-in feed) needs authenticated session cookies and is available only on the Enterprise plan, where access is reviewed case by case. Do not scrape personal data at scale, do not build shadow profiles of individuals, and respect GDPR and CCPA when any field could identify a person. Keep request volume modest, scrape only your own accounts or accounts you have permission to analyze, and prefer Meta's official Graph API and Instagram Basic Display alternatives for production use where they fit your need.

Extracto follows robots.txt by default and rate-limits politely. You are responsible for compliance with Instagram's terms and applicable law (GDPR, CCPA) in your use case.

Scraping Instagram: FAQ

Can Extracto scrape Instagram follower lists or private accounts?
No, not on standard plans. Follower lists, following lists, private accounts, Stories and the logged-in feed all require authenticated session cookies. That access is available only on the Enterprise plan, where it is reviewed case by case, and you should never collect personal data at scale or scrape accounts you do not own or have permission to analyze.
What public Instagram data can I actually get?
For a public profile that is reachable without login, you can typically extract top-level metadata: username, full name, biography, follower and following counts, post count, verification status, privacy flag, external bio URL and profile picture URL. Anything that requires scrolling a logged-in session or expanding follower lists falls behind the sign-in wall and is Enterprise only.
Why do I get null for some fields on Instagram profiles?
Extracto returns null instead of guessing when a field is not present in the page it received. On Instagram this usually means the value sits behind the login wall, the account is private, or that specific field was not rendered for logged-out visitors. A null is an honest signal that the data was not publicly available, not a silent failure or a fabricated number.
Do I need to handle proxies or anti-bot challenges myself?
No. Every Extracto request runs through a real headless browser with a managed anti-bot bypass layer and proxies handled for you, so protections like Cloudflare, DataDome and PerimeterX style defenses are managed without any setup on your side. You send one Instagram URL plus a JSON schema and receive typed, validated JSON back.
Is scraping Instagram legal?
Public, non-personal metadata in modest volume is lower risk, but Meta's Terms prohibit automated collection without written permission and robots.txt disallows most paths. Treat personal data carefully under GDPR and CCPA, keep volume low, prefer Meta's official Graph API where it fits, and consult counsel before any production use. Extracto is a tool, and compliance with each site's terms remains your responsibility.