JSON Feeds

JSON Feeds

Get easy access to Instagram feeds. Do what you want with them. No server-side code required.

How it works

Connect an Instagram account through our dashboard, create a feed, and we give you Instagram posts at a unique URL. Like this:

https://feeds.behold.so/zFgp2Jbbk23Ovf1ZUOhq

Pop that into your browser or Postman.

We handle API keys, usage limits, and creating and refreshing access tokens. We also offer multiple image sizes served from our CDN alongside useful image metadata like dimensions and prominant colors.

Creating a feed

  1. First, connect an Instagram account. Use a basic source to pull posts from a single Instagram account. If you want to show a feed of public hashtag posts, connect using an advanced source.
  2. Click + Add Feed in the Behold dashboard. Choose JSON, and pick a name for your feed. You can change this later.
  3. Click Create feed, and you’re all set! Click on your new feed to access your feed URL, settings and a preview of the response.

Feed settings

Number of Posts

The number of Instagram posts to fetch. This is capped based on your plan. Free plans can fetch up to 6 posts.

Allowed post types

This setting lets you choose which post types to include in your feed, from among images, videos , reels and albums.

Caption must include

Only posts that contain at least one of the text snippets you add here will be included in your feed. This is case-sensitive and can include spaces.

Caption may not include

Only posts that do not contain any of the text snippets you add here will be included in your feed. This is case-sensitive and can include spaces.

Hashtag feeds can take a few minutes to preload when combined with this setting.

Domain whitelist

This option blocks feed requests that do not originate from one of the whitelisted domains. If you leave this blank, all requests are allowed.

Subdomains are independent and wildcards are not supported. So example.com and www.example.com must be entered separately. The protocol (e.g. https://) is ignored.

localhost is always whitelisted.

Response format

GET requests to a valid feed URL will return a JSON object containing some metadata, alongside a posts field. Like so:

{
"username": "behold.examples",
"biography": "Fetch Instagram posts with your front-end JavaScript. No server-side code. No expiring tokens or app reviews. No worries.",
"profilePictureUrl": "https://cdn2-dev.behold.pictures/FpfDPCRPqWepfHqHLPOHVtlBr8s1/6853988604671387/profile.webp",
"website": "https://behold.so/",
"followersCount": 18,
"followsCount": 5,
"posts": [...]
}

The posts property contains an array of post objects:

"posts": [
{
"id": "17842915793354225",
"timestamp": "2020-09-04T22:27:19+0000",
"permalink": "https://www.instagram.com/p/CEuzou0hKS2/",
"mediaType": "IMAGE",
"mediaUrl": "https://scontent-dfw5-1.cdninstagram.com/v/t51.29350-15/118702810_419649599012814_4348560261050316974_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=18de74&_nc_ohc=3eOvUNOKvewAX88o-EP&_nc_ht=scontent-dfw5-1.cdninstagram.com&edm=ANo9K5cEAAAA&oh=00_AfDNfE7mTZZuLKjpwcjg2xgkfgA2T8MA0JmzZSeufQMFog&oe=65BE36D1",
"sizes": {
"small": {
"mediaUrl": "https://dev.behold.pictures/FpfDPCRPqWepfHqHLPOHVtlBr8s1/lEo51UnC6UFxwb3cxdPG/17842915793354225/small.webp",
"height": 400,
"width": 400
},
"medium": {
"mediaUrl": "https://dev.behold.pictures/FpfDPCRPqWepfHqHLPOHVtlBr8s1/lEo51UnC6UFxwb3cxdPG/17842915793354225/medium.webp",
"height": 700,
"width": 700
},
"large": {
"mediaUrl": "https://dev.behold.pictures/FpfDPCRPqWepfHqHLPOHVtlBr8s1/lEo51UnC6UFxwb3cxdPG/17842915793354225/large.webp",
"height": 1000,
"width": 1000
},
"full": {
"mediaUrl": "https://dev.behold.pictures/FpfDPCRPqWepfHqHLPOHVtlBr8s1/lEo51UnC6UFxwb3cxdPG/17842915793354225/full.webp",
"height": 1080,
"width": 1080
}
},
"caption": "Photo credit: Chuttersnap The year 1866 was signalised by a remarkable incident, a mysterious and puzzling phenomenon, which doubtless no one has yet forgotten. https://behold.so #saas #indiepreneur #indiehacker #ui #uiux #nocode #webaccessibility #a11y #julesverne",
"prunedCaption": "Photo credit: Chuttersnap The year 1866 was signalised by a remarkable incident, a mysterious and puzzling phenomenon, which doubtless no one has yet forgotten. https://behold.so",
"hashtags": [
"saas",
"indiepreneur",
"indiehacker",
"ui",
"uiux",
"nocode",
"webaccessibility",
"a11y",
"julesverne"
],
"mentions": [],
"colorPalette": {
"dominant": "196,104,25",
"muted": "96,163,124",
"mutedLight": "154,198,159",
"mutedDark": "95,107,60",
"vibrant": "223,110,18",
"vibrantLight": "239,189,88",
"vibrantDark": "13,104,69"
}
},
...
]

Posts contain the following fields:

id
string

The unique id of this Instagram post

timestamp
string

The date the post was published in ISO 8601 format.

permalink
string

The URL of the post on Instagram

mediaType
enum

Can be IMAGE, VIDEO, or CAROUSEL_ALBUM

isReel
boolean

Only included in video posts. true for reels. false for regular videos

mediaUrl
string

The original image or video source, straight from Instagram.

This image is usually very large and poorly optimized. For this reason the images in the sizes property are generally the correct choice for use in production.

For VIDEO posts, mediaUrl is where you will find the video source.

thumbnailUrl
string

The original thumbnail image from Instagram. Only included in VIDEO posts. The images in sizes are generally a better option.

sizes
object

This field contains four image size objects: small, medium, large and full. Each size has three fields: height,width and, mediaUrl. For video posts, the images in sizes are either drawn from the thumbnail or extracted from the first frame of the video if no thumbnail is available.

These images have been optimized, converted to webp format, and resized to the following maximum dimensions, with aspect ratio maintained:

  • Small: 400px
  • Medium: 700px
  • Large: 1000px
  • Full: 2000px

caption
string

The full original post caption

prunedCaption
string

The post caption with hashtags removed and trailing separators/whitespace cleaned up.

hashtags
array

An array of #hashtags extracted from the post caption

mentions
array

An array of @mentions extracted from the post caption

colorPalette
object

A range of colors extracted from the post, in R, G, B format. Useful for showing a meaningful placeholder color while the image loads.

children
array

An array of child media. Only included in CAROUSEL_ALBUM posts. Each child contains the following fields: id, mediaType, mediaUrl, sizes, and colorPalette.

Children will look something like this:

"children": [
{
"id": "18059393134510955",
"mediaType": "IMAGE",
"mediaUrl": "https://scontent-dfw5-1.cdninstagram.com/v/t51.29350-15/422239194_2133092217029319_3855568397770855431_n.jpg?_nc_cat=108&ccb=1-7&_nc_sid=18de74&_nc_ohc=MvRLWAeVBfQAX8PLdGr&_nc_ht=scontent-dfw5-1.cdninstagram.com&edm=APCawUEEAAAA&oh=00_AfC6GTeJ_uM-hTfglwWzZ29xuIpZeZOvXZCTKEUwCvTUaQ&oe=65BF2A98",
"sizes": {
"small": {
"mediaUrl": "https://cdn.behold.pictures/yZDwFyskeEQiF7cA6LW1gxe4RF02/Rw0EfjZRnj6IrmkY7HtP/18059393134510955/small.webp",
"height": 400,
"width": 320
},
"medium": {
"mediaUrl": "https://cdn.behold.pictures/yZDwFyskeEQiF7cA6LW1gxe4RF02/Rw0EfjZRnj6IrmkY7HtP/18059393134510955/medium.webp",
"height": 700,
"width": 560
},
"large": {
"mediaUrl": "https://cdn.behold.pictures/yZDwFyskeEQiF7cA6LW1gxe4RF02/Rw0EfjZRnj6IrmkY7HtP/18059393134510955/large.webp",
"height": 1000,
"width": 800
},
"full": {
"mediaUrl": "https://cdn.behold.pictures/yZDwFyskeEQiF7cA6LW1gxe4RF02/Rw0EfjZRnj6IrmkY7HtP/18059393134510955/full.webp",
"height": 1800,
"width": 1440
}
},
"colorPalette": {
"dominant": "170,155,144",
"muted": "154,126,92",
"mutedLight": "192,168,149",
"mutedDark": "49,99,46",
"vibrant": "52,183,248",
"vibrantLight": "86,197,250",
"vibrantDark": "107,37,17"
}
},
...
]

Extra advanced source fields

likeCount
number

The number of likes this post has received. This is only available when using an advanced source.

commentsCount
number

The number of comments on this post. This is only available when using an advanced source.

Hashtag feeds

Hashtag feeds will also include a hashtags field, with an array of hashtags that are the source of the feed. Individual posts in a hashtag feed will also have an additional hashtag field, which is the hashtag that caused the post to be included in the feed.

Where’s the alt text?

Unfortunately Instagram provides no official way of retrieving alt text at this time.

In most cases images from Instagram are purely decorative. That means that for accessibility purposes you should usually mark them up with an empty alt tag:

<img src="example.jpg" alt="" />

For more information, read the official WAI recommendations for decorative images.

Types

As a convenience we’ve published types for our JSON feeds on NPM:

Terminal window
# Install
npm install @behold/types
# or
pnpm add @behold/types
# or
yarn add @behold/types
// Import and apply
import type {
Feed,
Post,
ChildPost,
PostSizes,
PostSize,
ColorPalette,
RGBString,
} from "@behold/types"
const instaFeed: Feed = ...
// Import and apply
import type * as Behold from "@behold/types"
const instaFeed: Behold.Feed = ...

Ready to give it a try?

Sign up for free