Docs

The widget is one iframe. Everything after the first snippet is optional.

On this page

Embed the widget

Paste this where you want the widget to appear. It opens as a tool: your visitors paste any public link.

HTML
<iframe
  src="https://insta.flashdl.one/embed/?theme=light"
  title="Downloader for Instagram"
  width="100%" height="640"
  style="border:0;width:100%;max-width:560px;color-scheme:light"
  loading="lazy"
  referrerpolicy="strict-origin-when-cross-origin"
  sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-downloads"
  allow="clipboard-read; clipboard-write">
</iframe>
Attribute Why it is there
title Names the frame for screen readers.
width, style Full width of its column, up to 560px. The widget fits anything from 320px up. color-scheme:light stops a page with a dark color scheme from painting an opaque box behind the frame.
height 640px suits most pages. Add the auto-height script to size it to its content instead.
loading="lazy" The widget loads only when a visitor scrolls near it.
referrerpolicy Tells the widget your site’s name and nothing more. Your page paths stay private.
sandbox Limits what the widget can do. See Sandbox.
allow Lets the Paste button read the clipboard, and Copy write to it. Without it, visitors can still paste with the keyboard or a long press.

Sandbox

We recommend the sandbox attribute. It lists exactly what the widget may do. Anything not listed, the browser blocks.

Token What it allows Without it
allow-scripts The widget to run. Nothing works.
allow-same-origin The widget to reach its own server and remember the sponsor limit. Results can’t load.
allow-popups The first Download to open the sponsor tab, and links such as Open on Instagram to open. No new tabs. Downloads still work, but this tab is what keeps FlashDL free. Our terms ask you to keep this token.
allow-popups-to-escape-sandbox New tabs to open as normal pages. New tabs inherit the sandbox and may not display correctly.
allow-downloads Download to save files. Chrome and Edge block downloads without telling anyone.

Never add allow-top-navigation or allow-top-navigation-by-user-activation. The widget doesn’t need them, and leaving them out means the browser itself prevents the widget from navigating your page.

Parameters

Add parameters to the src address after /embed/.

Parameter Values Default What it does
url A link or @username, URL-encoded none Optional. Without it, the widget opens as a tool. With it, the widget opens with that post, Reel, profile, Story or Highlight already loaded. Visitors can still paste another link.
theme light, dark, auto light light unless set; auto follows each visitor’s light or dark setting from the first frame. Any other value is treated as light.

Accepted links: posts (/p/), Reels (/reel/, /reels/), /tv/, profiles, @username or a bare username, Stories (/stories/username/…) and Highlights (/stories/highlights/…). Links from m.instagram.com, without www, or with share parameters such as igsh all work. Short instagr.am links and /share/ links are not supported: open them in Instagram, tap Share, then Copy link, and use that.

Encode the value of url so its own ?, & and # don’t break the address.

Text
https://insta.flashdl.one/embed/?url=https%3A%2F%2Fwww.instagram.com%2Freel%2FABC123%2F&theme=dark
https://insta.flashdl.one/embed/?url=%40nasa&theme=auto

In code:

JavaScript
const src = 'https://insta.flashdl.one/embed/?url=' + encodeURIComponent(link) + '&theme=auto';
PHP
<?php $src = 'https://insta.flashdl.one/embed/?url=' . rawurlencode($link) . '&theme=auto'; ?>

In HTML attributes, write & as &amp; if your editor or validator asks for it. Both work in browsers.

One widget or many

  • Most sites need one. A single open tool handles every kind of public link.
  • Showing several posts? Give each its own iframe with its own url. Each widget looks up its link only when it scrolls into view, so a long page doesn’t fire every lookup at once.
  • Building pages with code? Make the url value from your post’s link, as in the examples above.

Auto-height

The widget reports its height to your page whenever its content changes. Add this script once, anywhere below the iframes, and every FlashDL widget on the page sizes itself. The message format, flashdl:height, is the same as the FlashDL widget for YouTube.

HTML
<script>
window.addEventListener('message', function (e) {
  if (e.origin !== 'https://insta.flashdl.one' || !e.data || e.data.type !== 'flashdl:height') return;
  var h = parseInt(e.data.height, 10);
  if (!h || h < 200) return;
  var frames = document.getElementsByTagName('iframe');
  for (var i = 0; i < frames.length; i++) {
    if (frames[i].contentWindow === e.source) frames[i].style.height = h + 'px';
  }
});
</script>

The origin check makes sure only our widget can resize your frames. Keep the height attribute on the iframe as the starting size.

Using the YouTube widget too? One script covers both. Replace the first line inside the function with:

JavaScript
if ((e.origin !== 'https://insta.flashdl.one' && e.origin !== 'https://embedded.flashdl.one') || !e.data || e.data.type !== 'flashdl:height') return;

Optional. Visitors sometimes arrive from inside an app such as Instagram or TikTok, whose built-in browsers often block downloads. The widget then offers a Copy link button so they can finish in their phone’s browser. Without the handshake below, that button copies a link to the widget on insta.flashdl.one with their Instagram link filled in. To send them back to your exact page instead, add this handshake:

HTML
<script>
window.addEventListener('message', function (e) {
  if (e.origin !== 'https://insta.flashdl.one' || !e.data || e.data.type !== 'flashdl:ready') return;
  e.source.postMessage({ type: 'flashdl:host', url: location.href }, 'https://insta.flashdl.one');
});
</script>

The widget keeps this address in the visitor’s browser, for that button only. Only your site’s name, which the widget already knows, is used for the sponsor link and analytics.

Messages and events

The widget and your page talk through postMessage. Every message is an object with a type. All of them are optional to handle.

From the widget to your page

type Fields When
flashdl:ready v (protocol version, currently 1) Once, when the widget is ready to use.
flashdl:height height (CSS pixels) Whenever the content height changes.
flashdl:event name, kind, code When something happens that you may want to count.
flashdl:scrollIntoView top (CSS pixels from the top of the widget) When a result or error appears out of view. Optional to handle.

Events sent with flashdl:event:

name Fields When
search kind A lookup started.
result kind A result is showing.
download_start kind A visitor started a download.
sponsor_open none A Download tap asked the browser for the sponsor tab. A pop-up blocker can still stop it.
error kind, code A lookup failed. code is a short reason, such as not_found or timeout.
cancel none The visitor cancelled a lookup.

kind says what the event is about, such as media (a post, Reel or carousel), profile, story or highlight. Treat values you don’t know as “other”. Events never include the link, username or caption.

From your page to the widget

type Fields What it does
flashdl:host url Sets the page link. See Page link.
flashdl:setTheme theme: auto, light or dark Switches the theme without reloading. Useful if your site has its own light and dark switch.
flashdl:setUrl url: a link or @username Looks it up, as if a visitor had pasted it.

Send them to the widget’s origin only:

JavaScript
frame.contentWindow.postMessage({ type: 'flashdl:setTheme', theme: 'dark' }, 'https://insta.flashdl.one');

Listen for events the same way as auto-height:

JavaScript
window.addEventListener('message', function (e) {
  if (e.origin !== 'https://insta.flashdl.one' || !e.data || e.data.type !== 'flashdl:event') return;
  console.log(e.data.name, e.data.kind, e.data.code);
});

Content-Security-Policy

If your site sends a Content-Security-Policy header, allow the widget’s frame:

Text
frame-src https://insta.flashdl.one;
  • If your policy has no frame-src, add it, or add the origin to child-src or default-src, whichever your policy uses.
  • The widget’s images and videos load inside its own frame, under our policy, so you don’t need to allow Instagram servers.
  • If you inline the auto-height script, your script-src must allow it with a hash or nonce, or move the script into a file on your own domain.
  • A Permissions-Policy header that blocks clipboard-read or clipboard-write overrides the allow attribute. Visitors can still paste by hand.
  • Pages that send Cross-Origin-Embedder-Policy: require-corp can’t show the widget.

Troubleshooting

What you see Likely cause Fix
Tapping Download does nothing The sandbox attribute is missing allow-downloads. Chrome and Edge then block downloads silently. Add allow-downloads, or remove the sandbox attribute.
The widget never shows results The sandbox attribute is missing allow-same-origin or allow-scripts. Use the full token list from Embed the widget.
An empty box where the widget should be Your Content-Security-Policy doesn’t allow the frame, or a browser extension blocks it. Add frame-src https://insta.flashdl.one.
The widget is cut off, or scrolls inside The fixed height is too small for the result. Add the auto-height script, or raise height.
The theme doesn’t match your site The widget is light unless theme says otherwise, and auto follows the visitor’s device, not your site’s own light and dark switch. Set theme to match, or send flashdl:setTheme when your switch changes.
On iPhone, a download seems to vanish Safari saves to Files › Downloads, not Photos. Open the file in Files, tap Share, then Save Video or Save Image. The download list is also in Safari’s address bar.
Downloads fail inside Instagram, Facebook or TikTok Their in-app browsers often block downloads. Visitors open the page in their phone’s browser. The widget shows them how. Add the page link handshake so they land on the right page.
A profile won’t load The account is private, renamed or deleted, or our source couldn’t reach it this time. Try again, or paste a link to one of the account’s posts.
A download fails after the result has been open for hours Instagram file links expire, after about a day for videos. Paste the link again for fresh links.

Limits

  • Public content only. Private accounts are not supported, and the widget never asks anyone to log in.
  • Video up to 720p. That is the highest quality the source provides for Reels, posts, Stories and Highlights. Photos come at the size Instagram provides, often 1080px wide.
  • Stories are live for 24 hours. A link to one Story shows all of that account’s current Stories, with the linked one first. If it has expired, the widget shows the ones still live.
  • No separate Reels tab on profiles. Reels appear with the other videos in the Posts grid.
  • File names are the ones Instagram servers give, which can be long.
  • Links in a result expire. Instagram file links last about a day for videos and a few days for photos. A fresh lookup fixes it.
  • Large files download straight from Instagram servers to your visitor’s device, so speed depends on their connection. In-app browsers may interrupt long downloads.
  • Now and then a public account can’t be loaded from our source. A direct link to one of its posts usually still works.

Changelog

Date Version Change
4 October 2026 1.0 First release: open tool, url and theme parameters, auto-height, page link handshake and events.