Fetch your own Instagram photos, videos, and Reels normalized to a flat shape. instapics is a small, zero-dependency client for the Instagram API with Instagram Login.
- Node.js ≥ 26.3
- A professional Instagram account and a Meta app with Instagram Login
pnpm add instapics
# or: npm install instapicsimport{Instapics}from'instapics';constig=newInstapics({token: process.env.IG_TOKEN});constme=awaitig.profile();// { id, username, account, posts }constmedia=awaitig.media(25);// 25 latest, any typeconstphotos=awaitig.photos(25);// images and albumsconstvideos=awaitig.videos(25);// feed videos, excluding Reelsconstreels=awaitig.reels(25);// Reels onlyconstone=awaitig.item('17895695668004550');// a single item by idfor(constphotoofphotos){console.log(photo.type,photo.url,photo.caption,photo.timestamp);}media, photos, videos, and reels return flat arrays — pagination and media-type filtering run inside the client, so you ask for n and get up to n back. The url and thumbnail fields point at Instagram's CDN.
Every item carries a thumbnail image url: the full-size image for photos and albums, the poster frame for videos and Reels.
// photo{id,type: 'photo',url,thumbnail,caption,permalink,timestamp}// video — type is 'reel' for Reels{id,type: 'video',url,thumbnail,caption,permalink,timestamp}// album (carousel, counted as a photo){id,type: 'album',url,thumbnail,items,caption,permalink,timestamp}// url, thumbnail — the first child of the carousel// items — the rest, as [{ type, url }, ...]Missing fields are null.
The token comes from the token option, falling back to process.env.IG_TOKEN:
newInstapics({ token });// explicitnewInstapics();// from process.env.IG_TOKENnewInstapics({env: mySecrets});// from a custom { IG_TOKEN } sourceLong-lived tokens last ~60 days. Refresh before expiry and the client switches to the new token automatically:
const{ token, expires }=awaitig.refresh();// expires is a Temporal.Instant| Option | Default | Meaning |
|---|---|---|
token | env.IG_TOKEN | Long-lived access token |
env | process.env | Object to read IG_TOKEN from |
baseUrl | https://graph.instagram.com | API host |
timeout | 30000 | Per-request timeout in ms; 0 disables |
Throws if no token resolves from token or env.
| Method | Returns |
|---|---|
profile() | { id, username, account, posts } |
media(count = 25) | latest media of any type |
photos(count = 25) | latest photos (images and albums) |
videos(count = 25) | latest feed videos (excludes Reels) |
reels(count = 25) | latest Reels |
item(id) | a single media object by numeric id |
refresh() | { token, expires }, and updates the client |
count is an integer from 0 to 1000. photos, videos, and reels scan up to the 2500 most recent posts to fill it, so a rare type may return fewer.
A failed request throws InstagramApiError, whether from an HTTP error, a network failure, or a timeout:
{(message,status,code,type,fbtraceId);}The Instagram Login API allows roughly 200 requests per hour per user token. instapics does not retry or back off; handle InstagramApiError (HTTP 429) and cache results in your application.
MIT. See LICENSE.