RSS Feed
Feedframer publishes an RSS 2.0 feed for each connected Instagram account. Use it with feed readers, email tools such as Mailchimp and Klaviyo, and anything else that reads RSS.
Get your feed URL
- Log in and open the RSS Feed page.
- Choose the account under Select Instagram Account.
- Copy the URL under Your RSS Feed URL.
The URL has this form:
https://feedframer.com/api/v1/rss?api_key=YOUR_API_KEY
The key is the account's API key, the same one shown on the Dashboard as "Feedframer API Token". Each connected account has its own key, so each account has its own feed.
To check the feed from a terminal:
curl "https://feedframer.com/api/v1/rss?api_key=YOUR_API_KEY"
What's in the feed
Items and plan limits
The feed lists the account's most recent posts, newest first. The number of items depends on your plan:
| Free | Premium | |
|---|---|---|
| Items in the feed | the 6 most recent posts | up to 100 most recent posts |
| Feedframer checks Instagram for new posts | daily | hourly |
The feed takes no other parameters. Filters, sorting and paging (filter[type], page[size], page[cursor] and so on) are ignored. If you need them, use the REST API instead.
A new Instagram post appears in the feed after Feedframer's next check of that account. See Caching below.
Channel
| Element | Content |
|---|---|
<title> |
@your_username - Instagram Feed |
<link> |
The Instagram profile, e.g. https://www.instagram.com/your_username/ |
<description> |
The account's Instagram bio. If there's no bio: Instagram posts from @your_username |
<language> |
en |
<lastBuildDate> |
When the feed was generated, in RFC 822 format |
<atom:link rel="self"> |
The feed's own URL, including your API key |
<image> |
The profile picture, with <url>, <title> and <link>. Left out if Feedframer has no stored profile picture. |
Items
Each post becomes one <item>:
| Element | Content |
|---|---|
<title> |
The caption on a single line, HTML stripped, cut to 100 characters with ... added if longer. If the post has no caption: @your_username - Image, @your_username - Video or @your_username - Carousel. |
<link> |
The post's Instagram permalink |
<guid isPermaLink="false"> |
The Instagram post id, e.g. 18123456789012345. It doesn't change, so feed readers and email tools can use it to spot posts they've already seen. |
<pubDate> |
When the post was published on Instagram, in RFC 822 format |
<description> |
HTML in a CDATA section (see below) |
<media:content> |
The post's media file, with url, type and medium attributes (see below) |
<media:thumbnail> |
Video posts only: the video's thumbnail image (url attribute) |
The <description> HTML contains, in order:
- An
<img>of the post. For videos this is the video's thumbnail, so it always shows a still image. For carousels it's the carousel's first image. - The full caption in a
<p>, with line breaks turned into<br />. Left out if there's no caption. - A "View on Instagram" link to the post.
<media:content> points at the stored media file. Its type follows the file:
.mp4files:type="video/mp4" medium="video"- everything else:
type="image/jpeg" medium="image"
Instagram doesn't always provide the video file for a reel. When it doesn't, Feedframer stores the thumbnail instead, so some video posts have an image <media:content>. Every video post has a <media:thumbnail>, and only video posts do, so that's the reliable way to spot a video in the feed.
The post type isn't written anywhere else in the item. The - Video style titles only appear when a post has no caption.
Carousel children, comments and like counts aren't in the feed. Use the REST API for those.
Example
A feed with one image post and one video post (values invented, whitespace tidied):
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<title>@your_username - Instagram Feed</title>
<link>https://www.instagram.com/your_username/</link>
<description>Your bio text</description>
<language>en</language>
<lastBuildDate>Wed, 30 Sep 2026 21:35:34 +0000</lastBuildDate>
<atom:link href="https://feedframer.com/api/v1/rss?api_key=YOUR_API_KEY" rel="self" type="application/rss+xml"/>
<image>
<url>https://cdn.feedframer.com/your_username/123_profile.jpg</url>
<title>@your_username</title>
<link>https://www.instagram.com/your_username/</link>
</image>
<item>
<title>Sunset over the harbour. Last light of the summer, taken from the old pier on the way home from...</title>
<link>https://www.instagram.com/p/ABC123def45/</link>
<guid isPermaLink="false">18123456789012345</guid>
<pubDate>Tue, 29 Sep 2026 18:30:00 +0000</pubDate>
<description><![CDATA[
<img src="https://cdn.feedframer.com/your_username/18123456789012345_media.jpg" alt="Sunset over the harbour. Last light of the summer, taken from the old pier on the way home from..." style="max-width: 100%; height: auto;"/>
<br/>
<p>Sunset over the harbour.<br />
Last light of the summer, taken from the old pier on the way home from work & worth the detour.</p>
<p><a href="https://www.instagram.com/p/ABC123def45/" target="_blank">View on Instagram</a></p>
]]></description>
<media:content url="https://cdn.feedframer.com/your_username/18123456789012345_media.jpg" type="image/jpeg" medium="image"/>
</item>
<item>
<title>@your_username - Video</title>
<link>https://www.instagram.com/reel/XYZ789ghi01/</link>
<guid isPermaLink="false">18098765432109876</guid>
<pubDate>Mon, 28 Sep 2026 09:15:00 +0000</pubDate>
<description><![CDATA[
<img src="https://cdn.feedframer.com/your_username/18098765432109876_thumbnail.jpg" alt="Instagram post" style="max-width: 100%; height: auto;"/>
<br/>
<p><a href="https://www.instagram.com/reel/XYZ789ghi01/" target="_blank">View on Instagram</a></p>
]]></description>
<media:content url="https://cdn.feedframer.com/your_username/18098765432109876_media.mp4" type="video/mp4" medium="video"/>
<media:thumbnail url="https://cdn.feedframer.com/your_username/18098765432109876_thumbnail.jpg"/>
</item>
</channel>
</rss>
Reading the feed in code
This Python script uses only the standard library. It prints each post and picks an image URL that works for every post type:
import urllib.request
import xml.etree.ElementTree as ET
FEED_URL = "https://feedframer.com/api/v1/rss?api_key=YOUR_API_KEY"
MEDIA = "{http://search.yahoo.com/mrss/}"
with urllib.request.urlopen(FEED_URL) as response:
channel = ET.parse(response).getroot().find("channel")
print(channel.findtext("title"))
for item in channel.findall("item"):
thumbnail = item.find(MEDIA + "thumbnail") # present on video posts only
content = item.find(MEDIA + "content")
is_video = thumbnail is not None
image_url = thumbnail.get("url") if is_video else (content.get("url") if content is not None else None)
print(item.findtext("pubDate"), "|", "video" if is_video else "image", "|", item.findtext("title"))
print(" ", item.findtext("link"))
print(" ", image_url)
Response headers
| Header | Value |
|---|---|
Content-Type |
application/rss+xml; charset=utf-8 |
X-Last-Fetched-At |
When Feedframer last checked Instagram for this account, e.g. 2026-09-30T19:50:34+00:00, or Never |
X-Feedframer-Account-Status |
State of the Instagram connection: ready, importing, refreshing_token or invalid_token. On every response. See Knowing when a feed has stopped updating. |
X-Feedframer-Feed-Stale |
Only present when the connection is broken. Plain-English explanation of when the feed froze and what fixes it. |
Caching
The feed is cached at Feedframer's edge for up to an hour, like the other API endpoints. The cache is cleared automatically when Feedframer finds new or changed posts, so a new post shows up in the feed right after the check that finds it. See Caching & Performance.
Your feed reader or email tool also decides how often it reads the feed. That can add its own delay.
Errors
Error responses are JSON, not XML, in the same format as the rest of the API. See Errors.
| HTTP | code |
Cause |
|---|---|---|
| 401 | MISSING_API_KEY |
The URL has no api_key |
| 401 | INVALID_API_KEY |
The key is wrong, has been regenerated, or its account was disconnected |
| 405 | METHOD_NOT_ALLOWED |
The request wasn't a GET |
For example:
{
"errors": [
{
"status": "401",
"code": "INVALID_API_KEY",
"title": "Authentication Failed",
"detail": "The provided API key is invalid."
}
]
}
Keep the URL private
The feed URL contains your API key. Anyone with the URL can read the account's posts through Feedframer. The key can't change anything; it only reads.
If the URL leaks, click Regenerate on the account's card on the Dashboard. The old key, and so the old feed URL, stops working immediately. Update the URL everywhere you use it.
Disconnecting an account also stops its feed. If you reconnect it later, it gets a new key and a new feed URL.
Troubleshooting
The feed doesn't show a new post
- Check
X-Last-Fetched-At, or the account card on the Dashboard, to see when Feedframer last checked Instagram. Free accounts are checked daily and premium accounts hourly. - To check sooner, click Refresh Posts on the Dashboard (once per 24 hours on Free, once per hour on Premium).
- If the feed has updated but your reader or email tool hasn't, the delay is on their side. Most have a refresh setting.
The feed returns an error
- Open the URL in a browser to see the error body.
INVALID_API_KEYusually means the key was regenerated or the account was disconnected and reconnected. Copy the current URL from the RSS Feed page.
Images don't show
- Many email clients block remote images until the reader allows them.
- Use the
<img>in<description>, or<media:thumbnail>for videos. A video's<media:content>is often an MP4, which won't display as an image.
Integration guides
Questions? Email [email protected] or use the contact page.