Getting Started

Introduction

This guide takes you from a new Feedframer account to your first API request. You'll connect an Instagram account, copy its API key and fetch your posts.

Prerequisites

You need:

  • An Instagram Business or Creator account. Personal accounts can't be connected, because Instagram's API only serves professional accounts. Connecting Instagram explains how to switch; it's free and takes a minute in the Instagram app.
  • A way to make HTTP requests, such as curl, a browser or your own code.

Step 1: Create your account

Go to feedframer.com/register and create a free account. No card is needed.

Step 2: Connect your Instagram account

  1. Open your Dashboard.
  2. Click Connect Account (or Connect Your First Account if you haven't connected one yet).
  3. Log in to Instagram and allow the permissions Feedframer asks for.
  4. Instagram sends you back to the Dashboard with your account connected.

Feedframer starts importing your posts straight away. The account's status shows Importing Posts... until the first import finishes, then Ready. You get an email when the account connects and another when your posts are ready.

The Free plan allows 1 Instagram account and Premium allows up to 5. Connecting Instagram covers permissions, statuses and fixing a connection.

Step 3: Copy your API key

Each connected Instagram account has its own API key. On the Dashboard, find the account's card and copy the value labelled Feedframer API Token. It's a 64-character string of lowercase letters and numbers.

The same key works for the REST API, the GraphQL API and the RSS feed. See Authentication for how keys work and how to regenerate one.

Step 4: Make your first request

Fetch your profile and posts with curl, replacing YOUR_API_KEY with your key:

curl 'https://feedframer.com/api/v1/me?api_key=YOUR_API_KEY'

Example response

{
  "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",
  "lastFetchAt": "2026-01-15T19:50:34+00:00",
  "posts": [
    {
      "id": "18123456789012345",
      "caption": "Sunset over the harbour #photography",
      "altText": null,
      "mediaType": "IMAGE",
      "mediaUrl": "https://cdn.feedframer.com/your_username/18123456789012345_media.jpg",
      "thumbnailUrl": null,
      "permalink": "https://www.instagram.com/p/ABC123def45/",
      "timestamp": "2026-01-15T18:30:00+00:00",
      "likeCount": 1542,
      "commentsCount": 87,
      "sizes": {
        "320": "https://cdn.feedframer.com/cdn-cgi/image/width=320,format=jpg/your_username/18123456789012345_media.jpg",
        "768": "https://cdn.feedframer.com/cdn-cgi/image/width=768,format=jpg/your_username/18123456789012345_media.jpg",
        "960": "https://cdn.feedframer.com/cdn-cgi/image/width=960,format=jpg/your_username/18123456789012345_media.jpg",
        "1200": "https://cdn.feedframer.com/cdn-cgi/image/width=1200,format=jpg/your_username/18123456789012345_media.jpg"
      }
    }
  ],
  "pagination": {
    "nextCursor": "eyJwdWJsaXNoZWRfYXQiOi...",
    "prevCursor": null,
    "hasMore": true,
    "perPage": 100
  }
}

The example is shortened to one post. What you get depends on your plan:

  • Free: your 6 most recent posts. There is no sizes field, and pagination is always {"nextCursor": null, "prevCursor": null, "hasMore": false, "perPage": 6}.
  • Premium: up to 100 posts per request, a sizes field with resized images, and a nextCursor to fetch the next page when hasMore is true. See Pagination.

A few things to know about posts:

  • mediaType is IMAGE, VIDEO or CAROUSEL_ALBUM. Reels come back as VIDEO.
  • For a VIDEO post, mediaUrl is usually an .mp4 file. Use thumbnailUrl for the poster image, not mediaUrl.
  • caption, likeCount and commentsCount can be null, and altText almost always is.

The REST API reference describes every field and parameter.

Step 5: Show your posts on a page

This example fetches your posts in the browser and adds them to the page as linked images. It works with Free and Premium keys.

<div id="instagram-feed"></div>

<script>
  const apiKey = 'YOUR_API_KEY';

  async function loadFeed() {
    const response = await fetch(`https://feedframer.com/api/v1/me?api_key=${apiKey}`);
    const body = await response.json();

    if (!response.ok) {
      // Errors look like {"errors": [{"status": "401", "code": "INVALID_API_KEY", ...}]}
      throw new Error(`${body.errors[0].code}: ${body.errors[0].detail}`);
    }

    const feed = document.getElementById('instagram-feed');

    for (const post of body.posts) {
      // Video posts: mediaUrl is the video file, so show the thumbnail instead.
      const image = post.mediaType === 'VIDEO' ? post.thumbnailUrl : post.mediaUrl;

      const link = document.createElement('a');
      link.href = post.permalink;

      const img = document.createElement('img');
      img.src = image;
      img.alt = post.altText || post.caption || 'Instagram post';
      img.width = 320;

      link.appendChild(img);
      feed.appendChild(link);
    }
  }

  loadFeed().catch((error) => console.error(error));
</script>

On Premium you can use the smaller post.sizes['320'] image instead of the full-size mediaUrl when sizes is present.

Your API key is safe to use in browser code like this. It only reads posts that are already public on Instagram. See Authentication.

Step 6: Try GraphQL or RSS (optional)

GraphQL

The GraphQL API has a me query that returns the same profile and posts. Ask for only the fields you need:

query {
  me {
    username
    posts {
      id
      type
      caption
      mediaUrl
      thumbnailUrl
      permalink
      publishedAt
    }
    pagination {
      nextCursor
      hasMore
    }
  }
}

Send it with curl:

curl -X POST 'https://feedframer.com/graphql?api_key=YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"query": "{ me { username posts { id type caption mediaUrl thumbnailUrl permalink publishedAt } pagination { nextCursor hasMore } } }"}'

The response is wrapped in data:

{
  "data": {
    "me": {
      "username": "your_username",
      "posts": [
        {
          "id": "1234",
          "type": "IMAGE",
          "caption": "Sunset over the harbour #photography",
          "mediaUrl": "https://cdn.feedframer.com/your_username/18123456789012345_media.jpg",
          "thumbnailUrl": null,
          "permalink": "https://www.instagram.com/p/ABC123def45/",
          "publishedAt": "2026-01-15T18:30:00+00:00"
        }
      ],
      "pagination": {
        "nextCursor": null,
        "hasMore": false
      }
    }
  }
}

GraphQL names some fields differently from REST: type instead of mediaType, and publishedAt instead of timestamp. The GraphQL id is Feedframer's own post id; the Instagram id is in instagramPostId. When you're logged in, you can try queries in the GraphQL Explorer. See the GraphQL API reference.

RSS

Your RSS feed URL is:

https://feedframer.com/api/v1/rss?api_key=YOUR_API_KEY

It contains your latest posts, newest first: 6 on Free, up to 100 on Premium. Use it in Mailchimp, Klaviyo or any RSS reader. See RSS Feed.

Step 7: Experiment in the API Playground

The API Playground lets you build REST requests without writing code:

  1. Pick the Instagram account to query.
  2. Set filters, sorting and page size.
  3. Click Send Request to see the response.
  4. Copy the generated code in JavaScript, PHP, cURL or Python.

Next steps

Common issues

INVALID_API_KEY or MISSING_API_KEY

Both return HTTP 401. MISSING_API_KEY means the request had no api_key query parameter; the key can't be sent in a header. INVALID_API_KEY means the key isn't recognised. Copy the key again from the Dashboard: it's 64 characters, lowercase letters a–f and digits only. A key also stops working when you regenerate it or disconnect its Instagram account.

No posts returned

If you've just connected your account, wait until its status on the Dashboard changes from Importing Posts... to Ready.

If you filter by type or date on the Free plan, the filter applies to your 6 most recent posts only. For example, filter[type]=VIDEO returns no posts if none of your latest 6 are videos.

Only 6 posts returned

That's the Free plan limit, even if you ask for a larger page[size]. Premium returns up to 100 posts per request and lets you page through older ones.

Posts are out of date

Free accounts update daily and Premium accounts hourly. To update sooner, click Refresh Posts on the account's Dashboard card (once every 24 hours on Free, once an hour on Premium). In production, responses are cached for up to an hour; see Caching & Performance.

Instagram connection failed

Check that the Instagram account is a Business or Creator account. Connecting Instagram covers the other causes.

Need help?