Instagram API Documentation

1. Overview

The API is based on the query language GraphQL. This language is used by Instagram for its APIs, so it is the best way to mimic Graph API. You can get more info by the following links:

GraphQL

Relay Cursor Connections Specification

GraphQL Server Specification

What Data 365 Instagram API is

We are launching a new Hashtag Search feature for Businesses on Instagram. With this new feature, businesses will still be able to discover content, measure the reach of their marketing campaigns, and understand the public sentiment around their brand.

With deprecation date for Hashtag Search via Instagram in mind, our team has been working to create an API which enables appropriate business use-cases, while protecting user privacy and safety.

To learn more, please check our developer documentation and contact us.

What Instagram data you can get

Information on Instagram media:

  • created time
  • text, list of hashtags
  • image URL, video preview URL
  • engagement (likes count, video views count, comments count)
  • a list of comments (text, created_time, the author`s username)
  • owner info (username, full name, profile photo thumbnail)

Information about a public Instagram page:

  • full name
  • biography
  • profile photo
  • a detailed list of latest publications
  • followers count, followings count, media count

Instagram search by hashtag:

  • total count of the posts with a hashtag
  • a detailed list of the latest posts with a hashtag

2. General info and limitations

We update data only when you request it:

  • If we have it in our database, we will provide the cached version and we’ll start updating the data (to provide the newest data after the second/third request). After each request, you will have all the information that we managed to load till that moment (old data + new data that was downloaded till that moment; or fully new data if loading had been already finished)

  • If we don’t have it in our database, we will send you a message that we are downloading data at this moment. Our server loads data from Instagram to our database. You should repeat the request. You’ll receive the data instead of the message as soon as we’ll finish downloading.

We provide two fields to help understand the “age” of data:

  • last_update. UNIX timestamp when we last updated data in our database;
  • is_being_updated. It’s True if we are in the process of updating. It’s False if it has been already updated.

For the basic pricing plan*:

  • a post is considered updated for 2 hours since the last update
  • a profile is considered updated for 24 hours since the last update
  • we don’t update data if it has been updated less than 2 hours ago. You can get the cached version only
  • we don’t update old posts (older than 1 week) as they get minimal engagement increment

For the basic pricing plan, we load only*:

  • 100 latest posts per hashtag
  • 250 comments per media
  • The first 100 posts from Instagram page
*We can change time limits upon request for an additional fee

Individual plan:

  • We can change the basic plan limits on media, comments, and profiles
  • Extra fields for posts, profiles, comments
  • API customization (request or response formats, webhooks, etc)
  • Demographic data

3. Request format

We use Graph API style for requests. API accepts only GET requests. The access token is provided by us. Instagram API request takes the following form:

GET
https://api.singularex.com/instagram/
<node-type>/<node-ID>
?fields=<graph-request>
&access_token=<your_access_token>

We provide endpoints (node-type) for 3 types of data:

  • media (post, like Car)
GET
https://api.singularex.com/instagram/
media/1770093817144369706
?fields=id,shortcode,created_time,media_url
&access_token=<your_access_token>
  • tag (hashtag info and posts with a hashtag, like #spacex)
GET
https://api.singularex.com/instagram/
tag/juice
?fields=id,media_count,profile_pic_url,last_update,is_being_updated
&access_token=<your_access_token>
GET
https://api.singularex.com/instagram/
user/spacex
?fields=id,username,media.first(1){edges{node{shortcode,created_time,timestamp,media_type,media_url,caption,
tagged_user_media,tagged_user_text,tags,like_count,comment_count,video_view_count,
location{id,name,slug,has_public_page},
owner{id,username,full_name,profile_pic_url},
comments.first(1){edges{node{id,parent_id,created_time,timestamp,text,
owner{id,username,full_name,profile_pic_url}}}}}}}
&access_token=<your_access_token>

Certain parameters are required while others are optional. As is standard in URLs, all parameters are separated using the ampersand (&) character.

4. /media (Graph scheme of the endpoint)

Request format:
GET
https://api.singularex.com/instagram/
media/<media-ID or media-shortcode>
?fields=<graph-request>
&access_token=<your_access_token>
API scheme:
BODY
{
	media: InstagramMedia {
		id: ID
		shortcode: String
		created_time: Datetime  # ISO 8601 format
		timestamp: Int  # UNIX timestamp
		media_type: String
		media_url: String
		caption: [String]
		tagged_user_media: [String]
		tagged_user_text: [String]
		tags: [String]
		like_count: Int
		comment_count: Int
		video_view_count: Int
		owner_id: ID
		location_id: ID
		last_update: Int  # UNIX timestamp
		is_being_updated: Boolean
		location: InstagramLocation {
			id: ID
			name: String
			slug: String
			has_public_page: Boolean
		}
		owner: InstagramNodeOwner {
			id: ID
			username: String
			profile_pic_url: String
			type: String
			full_name: String
		}
		comments: InstagramCommentsConnection {
			page_info: PageInfo {
				has_next_page: Boolean
				has_previous_page: Boolean
				start_cursor: String
				end_cursor: String
			}
			edges: Edges {
				node: InstagramComment {
					id: ID
					parent_id: ID  # ID of parent media
					created_time  # ISO 8601 format
					timestamp  # UNIX timestamp
					text: String
					owner_id: ID
					last_update: Int  # UNIX timestamp
					is_being_updated: Boolean
					owner: InstagramNodeOwner {
						id: ID
						username: String
						profile_pic_url: String
						type: String
						full_name: String
					}
				}
			}
		}
	}
}

5. /user (Graph scheme of the endpoint)

Response filters:

  • from_timestamp, to_timestamp - filter media by date posted. Format: timestamp
  • from_date, to_date - filter media by date posted. Format: yyyy-mm-dd

Note:

All filters must be sent as separate GET-params in request URL, for example:
&from_date=2019-06-20&to_date=2019-06-25 or
&from_timestamp=1540000000&to_timestamp=1550000000

Request format:
GET
https://api.singularex.com/instagram/
user/<username>
?fields=<graph-request>
&access_token=<your_access_token>
API scheme:
BODY
{
	user: InstagramUser {
		id: ID
		username: String
		profile_pic_url: String
		type: String
		full_name: String
		biography: String
		external_url: String
		connected_fb_page: String
		is_private: Boolean
		is_verified: Boolean
		follower_count: Integer
		follow_count: Integer
		media_count: Integer
		saved_media_count: Integer
		collection_count: Integer
		last_update: Int # UNIX timestamp
		is_being_updated: Boolean
		media: InstagramMediaConnection {
			page_info: PageInfo {
				has_next_page: Boolean
				has_previous_page: Boolean
				start_cursor: String
				end_cursor: String
			}
			edges: Edges {
				node: InstagramMedia {
					...
					# Same fields as in the instagram.media
					...
				}
			}
		}
	}
}

6. /tag (Graph scheme of the endpoint)

Response filters:

  • from_timestamp, to_timestamp - filter media by date posted. Format: timestamp
  • from_date, to_date - filter media by date posted. Format: yyyy-mm-dd

Note:

All filters must be sent as separate GET-params in request URL, for example:
&from_date=2019-06-20&to_date=2019-06-25 or
&from_timestamp=1540000000&to_timestamp=1550000000

Request format:
GET
https://api.singularex.com/instagram/
tag/<tag-name>
?fields=<graph-request>
&access_token=<your_access_token>
API scheme:
BODY
{
	tag: InstagramTag {
		id: String # tag name without hashtag symbol
		profile_pic_url: String
		media_count: Int
		last_update: Int # UNIX timestamp
		is_being_updated: Boolean
		media: InstagramMediaConnection {
			page_info: PageInfo {
				has_next_page: Boolean
				has_previous_page: Boolean
				start_cursor: String
				end_cursor: String
			}
			edges: Edges {
				node: InstagramMedia {
					…
					# Same fields as in the instagram.media
					…
				}
			}
		}
	}
}

7. Sample request and response

For example, to get info about media with tag #juice you need to make the next request:

Tag request
GET
https://api.singularex.com/instagram/
tag/juice
?fields=id,media_count,profile_pic_url,last_update,is_being_updated
&access_token=<your_access_token>
Tag response
BODY
{
    "error": {},
    "data": {
        "id": "juice",
        "media_count": 7979876,
        "profile_pic_url": "https://scontent-frx5-1.cdninstagram.com/vp/53bf5417386018688db2026becc5e1b2/5D7CE102/t51.2885-15/e35/c0.180.1440.1440a/s150x150/59967397_1041572172698184_788691368965451057_n.jpg?_nc_ht=scontent-frx5-1.cdninstagram.com",
        "last_update": 1559150950,
        "is_being_updated": false
    },
    "status": "ok"
}

For example, to get info about media with ID=1770093817144369706 you need to make the next request:

Media request
GET
https://api.singularex.com/instagram/
media/1770093817144369706
?fields=id,shortcode,created_time,media_url
&access_token=<your_access_token>
Media response
BODY
{
    "error": {},
    "data": {
        "id": "1770093817144369706",
        "shortcode": "BiQovLGAWIq",
        "created_time": "2018-05-02T03:27:28",
        "media_url": "https://scontent-arn2-1.cdninstagram.com/vp/fad582c6f3702b6dc555acd344faef47/5D280A56/t51.2885-15/e35/30841940_161598917841784_3832690349499744256_n.jpg?_nc_ht=scontent-arn2-1.cdninstagram.com"
    },
    "status": "ok"
}

If you want to get info about media’s owner, just add one more field:

Media`s owner request
GET
https://api.singularex.com/instagram/
media/1770093817144369706
?fields=id,shortcode,created_time,media_url,
owner{id,username,profile_pic_url}
&access_token=<your_access_token>
Media`s owner response
BODY
{
    "error": {},
    "data": {
        "id": "1770093817144369706",
        "shortcode": "BiQovLGAWIq",
        "created_time": "2018-05-02T03:27:28",
        "media_url": "https://scontent-arn2-1.cdninstagram.com/vp/fad582c6f3702b6dc555acd344faef47/5D280A56/t51.2885-15/e35/30841940_161598917841784_3832690349499744256_n.jpg?_nc_ht=scontent-arn2-1.cdninstagram.com",
        "owner": {
            "id": "3008836221",
            "username": "teslamotorsports",
            "profile_pic_url": "https://scontent-arn2-1.cdninstagram.com/vp/d3c0da6a1364fbc4c6a1ee22548177c7/5D12A1B2/t51.2885-19/s150x150/36136080_195401041310743_524733991551500288_n.jpg?_nc_ht=scontent-arn2-1.cdninstagram.com"
        }
    },
    "status": "ok"
}

And first comment + owner info for comment:

First comment + owner request
GET
https://api.singularex.com/instagram/
media/1770093817144369706
?fields=id,shortcode,created_time,owner{id,username},
comments.first(1){edges{node{id,text,owner{id,username}}}}
&access_token=<your_access_token>
First comment + owner response
BODY
{
    "error": {},
    "data": {
        "id": "1770093817144369706",
        "shortcode": "BiQovLGAWIq",
        "created_time": "2018-05-02T03:27:28",
        "owner": {
            "id": "3008836221",
            "username": "teslamotorsports"
        },
        "comments": {
            "edges": [
                {
                    "node": {
                        "id": "17927679481127546",
                        "timestamp": 1525641658,
                        "last_update": 1551696861,
                        "is_being_updated": false,
                        "text": "Those brake pads ????",
                        "owner": {
                            "id": "527779220",
                            "username": "steffenology"
                        }
                    }
                }
            ]
        }
    },
    "status": "ok"
}

8. Getting next pages request

To get next pages use page_info’s fields has_next_page, has_previous_page, start_cursor, end_cursor. You can get more info by following the link: Relay Cursor Connections Specification


The has_next_page and has_previous_page values are false in the case when your request displays all available media. The following endpoints should only be used with restrictions such as media.first(5) or media.last(10).


For example, to get the next 5 media, use the value end_cursor in the endpoint such as media.first(5).after(“end_cursor”). The end_cursor value is taken from the previous request such as media.first(5).


To get the previous 5 media, use the value start_cursor in the endpoint such as media.last(5).before(“start_cursor”). The start_cursor value is taken from the previous request such as media.last(5).


Note that the start_cursor and end_cursor values must be in quotes.
Media request from 1 to 3:
GET
https://api.singularex.com/instagram/
tag/photography
?fields=id,
media.first(3){page_info{has_next_page,start_cursor,end_cursor},edges{node{id}}}
&access_token=<your_access_token>
Media response from 1 to 3:
BODY
{
    "error": {},
    "data": {
        "id": "photography",
        "media": {
            "page_info": {
                "has_next_page": true,
                "start_cursor": "YXJyYXljb25uZWN0aW9uOjA=",
                "end_cursor": "YXJyYXljb25uZWN0aW9uOjI="
            },
            "edges": [
                {
                    "node": {
                        "id": "2065332295327345047",
                        "timestamp": 1560426817,
                        "last_update": 1560427709,
                        "is_being_updated": false
                    }
                },
                {
                    "node": {
                        "id": "2065330707747587078",
                        "timestamp": 1560426628,
                        "last_update": 1560427712,
                        "is_being_updated": false
                    }
                },
                {
                    "node": {
                        "id": "2065325341622271037",
                        "timestamp": 1560425988,
                        "last_update": 1560426993,
                        "is_being_updated": false
                    }
                }
            ]
        }
    },
    "status": "ok"
}
Media request from 4 to 6:
GET
https://api.singularex.com/instagram/
tag/photography
?fields=id,
media.first(3).after("YXJyYXljb25uZWN0aW9uOjI="){page_info{has_next_page,start_cursor,end_cursor},edges{node{id}}}
&access_token=<your_access_token>
Media response from 4 to 6:
BODY
{
    "error": {},
    "data": {
        "id": "photography",
        "media": {
            "page_info": {
                "has_next_page": true,
                "start_cursor": "YXJyYXljb25uZWN0aW9uOjM=",
                "end_cursor": "YXJyYXljb25uZWN0aW9uOjU="
            },
            "edges": [
                {
                    "node": {
                        "id": "2065325342754604765",
                        "timestamp": 1560425988,
                        "last_update": 1560426991,
                        "is_being_updated": false
                    }
                },
                {
                    "node": {
                        "id": "2065325341632498158",
                        "timestamp": 1560425988,
                        "last_update": 1560426996,
                        "is_being_updated": false
                    }
                },
                {
                    "node": {
                        "id": "2065325341395840663",
                        "timestamp": 1560425988,
                        "last_update": 1560426990,
                        "is_being_updated": false
                    }
                }
            ]
        }
    },
    "status": "ok"
}

9. Response parameters

Responses are encoded in JSON format and have 3 fields: status, data, and error.

200

If everything is OK (HTTP response: 200 OK or 202 Accepted):

  • status will be ‘ok’ or ‘accepted
  • data field will contain requested data or will be empty if the status is ‘accepted’
Example:
GET
https://api.singularex.com/instagram/
media/1770093817144369706
?fields=id,shortcode,created_time,owner{id,username}
Response:
BODY
{
    "error": {},
    "data": {
        "id": "1770093817144369706",
        "shortcode": "BiQovLGAWIq",
        "created_time": "2018-05-02T03:27:28",
        "owner": {
            "id": "3008836221",
            "username": "teslamotorsports"
        }
    },
    "status": "ok"
}

Otherwise, if something is not OK:

  • error type will be in the status field
  • data field will be empty
  • error info will be stored in the error field

202

RequestAccepted (HTTP response: 202 Accepted)

Cannot find the requested node in a cache. Starting the parsing process. Repeat request later.

Response:
BODY
{
    "error": {
        "message": "Some nodes you requested are being loaded now: 12345. Try again later",
        "type": "RequestAccepted"
    },
    "data": {},
    "status": "accepted"
}

400

InvalidRequestError (HTTP response: 400 Bad Request)

The graph request is invalid. Repeat request later

Response:
BODY
{
    "error": {
        "message": "Cannot query field \"id_\" on type \"Media\". Did you mean \"id\"?",
        "type": "InvalidRequestError"
    },
    "data": {},
    "status": "InvalidRequestError"
}

403

AuthenticationError (HTTP response: 403 Forbidden)

The access token examination has failed. The access token is not provided or invalid.

Response:
BODY
{
    "error": {
        "message": "Invalid access token",
        "type": "AuthenticationError"
    },
    "data": {},
    "status": "AuthenticationError"
}

404

NodeNotExistsError (HTTP response: 404 Not Found)

A page for the requested node does not exist or cannot be loaded.

Response:
BODY
{
    "error": {
        "message": "Some nodes you requested cannot be loaded: 1690",
        "type": "NodeNotExistsError"
    },
    "data": {},
    "status": "NodeNotExistsError"
}

500

InternalServerError (HTTP response: 500 Internal Server Error)

Something was wrong on our side.

Response:
BODY
{
    "error": {
        "message": "Internal server error",
        "type": "InternalServerError"
    },
    "data": {},
    "status": "InternalServerError"
}
Contact us and get a free trial period
Need help? Don't hesitate to ask us something
Fill in this form and we'll respond to you
You agree with our Terms and Conditions