Instagram Accounts API
Overview
GET /api/v1/accounts returns the profile of the Instagram account your API key belongs to: username, display name, bio, profile picture, follower counts, and the account's status in Feedframer.
Each connected Instagram account has its own API key, and a key only reads its own account. So this endpoint always returns exactly one account, even if you have several connected on Premium. To read another account, use that account's key.
If you also need posts, you may not need this endpoint at all. GET /api/v1/me returns the same profile fields plus the posts. Use /api/v1/accounts when you only want the profile, or when you need status, instagramUserId or the timestamps below, which /me doesn't include.
Endpoint
GET https://feedframer.com/api/v1/accounts?api_key=YOUR_API_KEY
Parameters
| Parameter | Notes |
|---|---|
api_key |
Required. Your API key, from the account's card on the Dashboard. |
The endpoint takes no other parameters. Anything else in the query string is ignored.
Response format
The response follows the JSON:API resource format: a data array with one resource, and a meta object. The Content-Type is application/json.
Success response (200 OK)
{
"data": [
{
"type": "instagram-accounts",
"id": "42",
"attributes": {
"instagramUserId": "17841400000000000",
"username": "your_username",
"name": "Your Name",
"biography": "Your bio text",
"website": "https://example.com",
"profilePictureUrl": "https://cdn.feedframer.com/your_username/123_profile.jpg",
"followersCount": 1234,
"followsCount": 567,
"mediaCount": 89,
"status": "ready",
"profileLastUpdatedAt": "2026-09-30T08:00:00+00:00",
"lastFetchAt": "2026-09-30T19:50:34+00:00"
}
}
],
"meta": {
"total": 1
}
}
Top-level fields
| Field | Type | Notes |
|---|---|---|
data |
array | Always exactly one resource: the key's account. |
data[].type |
string | Always instagram-accounts. |
data[].id |
string | Feedframer's id for the account. This is not the Instagram user id. |
data[].attributes |
object | The account's fields, below. |
meta.total |
integer | Always 1. |
There are no links in the response.
Attributes
| Field | Type | Notes |
|---|---|---|
instagramUserId |
string | Instagram's id for the account. |
username |
string | Instagram username, without the @. |
name |
string or null | Display name on Instagram. |
biography |
string or null | Bio text. May contain line breaks. |
website |
string or null | Website from the Instagram profile. |
profilePictureUrl |
string or null | Profile picture. Usually a copy on cdn.feedframer.com. |
followersCount |
integer or null | Followers. |
followsCount |
integer or null | Accounts this account follows. |
mediaCount |
integer or null | Total posts on Instagram, not just the ones Feedframer returns. |
status |
string | The account's connection status in Feedframer. See below. |
profileLastUpdatedAt |
string or null | When the profile fields were last refreshed from Instagram, ISO 8601. |
lastFetchAt |
string or null | When Feedframer last fetched the account's posts, ISO 8601. null if it hasn't yet. The same time is sent in the X-Last-Fetched-At header on /api/v1/me and /api/v1/rss. |
Profile data updates
Profile fields (bio, follower counts, profile picture and so on) refresh at most once a day, when posts are fetched. profileLastUpdatedAt shows when that last happened. Posts refresh daily on Free and hourly on Premium; lastFetchAt shows the last post fetch.
Account status values
status |
Meaning |
|---|---|
ready |
Connected and working. |
importing |
Feedframer is importing the account's posts: just after the account is connected, or after the owner presses "Refresh Posts" on the Dashboard. The key works and serves the posts already stored. |
refreshing_token |
Feedframer is renewing the account's Instagram access token. This happens automatically before the token expires. |
invalid_token |
Instagram no longer accepts the account's access token, so Feedframer can't fetch new posts. The key still works and serves the last posts Feedframer stored. The Dashboard shows "Invalid Token", and the owner is emailed to reconnect. Reconnecting fixes it and keeps the same key. |
A disconnected account doesn't have a status you can read. Its key returns a 401 with the code INVALID_API_KEY.
Example requests
cURL
curl 'https://feedframer.com/api/v1/accounts?api_key=YOUR_API_KEY'
JavaScript (fetch)
const apiKey = 'YOUR_API_KEY';
const response = await fetch(`https://feedframer.com/api/v1/accounts?api_key=${apiKey}`);
const body = await response.json();
if (!response.ok) {
// Every error has an errors array with a code, e.g. INVALID_API_KEY
throw new Error(`${body.errors[0].code}: ${body.errors[0].detail}`);
}
const account = body.data[0].attributes;
console.log(`@${account.username}: ${account.status}`);
PHP
<?php
$apiKey = 'YOUR_API_KEY';
$url = 'https://feedframer.com/api/v1/accounts?api_key=' . urlencode($apiKey);
// ignore_errors lets us read the JSON body of 4xx and 5xx responses
$context = stream_context_create(['http' => ['ignore_errors' => true]]);
$body = json_decode(file_get_contents($url, false, $context), true);
if (isset($body['errors'])) {
$error = $body['errors'][0];
throw new RuntimeException("{$error['code']}: {$error['detail']}");
}
$account = $body['data'][0]['attributes'];
echo "@{$account['username']}: {$account['status']}\n";
Python
import requests
api_key = 'YOUR_API_KEY'
response = requests.get(
'https://feedframer.com/api/v1/accounts',
params={'api_key': api_key},
)
body = response.json()
if not response.ok:
error = body['errors'][0]
raise RuntimeError(f"{error['code']}: {error['detail']}")
account = body['data'][0]['attributes']
print(f"@{account['username']}: {account['status']}")
Use cases
Display a profile header
<div class="profile">
<img class="profile-pic" alt="" />
<a class="username"></a>
<p class="bio"></p>
<p><span class="followers"></span> followers</p>
</div>
<script>
const apiKey = 'YOUR_API_KEY';
fetch(`https://feedframer.com/api/v1/accounts?api_key=${apiKey}`)
.then((response) => response.json())
.then((body) => {
if (body.errors) {
console.error(body.errors[0].code);
return;
}
const account = body.data[0].attributes;
if (account.profilePictureUrl) {
document.querySelector('.profile-pic').src = account.profilePictureUrl;
}
const link = document.querySelector('.username');
link.textContent = `@${account.username}`;
link.href = `https://www.instagram.com/${account.username}/`;
// textContent keeps the bio's text safe; name, bio and counts can be null
document.querySelector('.bio').textContent = account.biography ?? '';
document.querySelector('.followers').textContent =
(account.followersCount ?? 0).toLocaleString();
});
</script>
Warn when the account needs reconnecting
status tells you when Instagram has stopped accepting the account's token, so new posts won't arrive until the owner reconnects:
const body = await (await fetch(`https://feedframer.com/api/v1/accounts?api_key=${apiKey}`)).json();
const { status, lastFetchAt } = body.data[0].attributes;
if (status === 'invalid_token') {
console.warn(`Instagram token is invalid. Last successful fetch: ${lastFetchAt}. Reconnect on the Feedframer Dashboard.`);
}
Profile and posts together
/api/v1/me already includes the profile fields (username, name, biography, website, profilePictureUrl, followersCount, followsCount, mediaCount). For a profile header plus a feed, one request to /me is enough:
const response = await fetch(`https://feedframer.com/api/v1/me?api_key=${apiKey}`);
const feed = await response.json();
renderProfile(feed); // feed.username, feed.profilePictureUrl, ...
renderPosts(feed.posts); // up to 6 posts on Free, 100 on Premium
Error responses
Errors use the JSON:API error format with the Content-Type application/vnd.api+json. There are no rate limits.
401: missing API key
{
"errors": [
{
"status": "401",
"code": "MISSING_API_KEY",
"title": "Authentication Required",
"detail": "An API key is required. Please provide your API key using the api_key parameter."
}
]
}
401: invalid API key
Returned for an unknown key, a key that has been regenerated, or a key for a disconnected account.
{
"errors": [
{
"status": "401",
"code": "INVALID_API_KEY",
"title": "Authentication Failed",
"detail": "The provided API key is invalid."
}
]
}
Other requests, such as a POST (405, METHOD_NOT_ALLOWED), get the same error format. See Error Handling.
Caching
In production, successful responses are cached at the edge for an hour. The cache is cleared when the account's key is regenerated or the account is disconnected, and you can clear it from the Dashboard with "Purge Cache". See Caching & Performance.
Next steps
- REST API: the full
/api/v1/mereference - GraphQL API: the same data over GraphQL
- Authentication: finding and regenerating keys