Embed: iframe parameter
The
iframe parameter asks Microlink to discover the provider's official interactive embed for the target URL — a real YouTube player, a Spotify track, a Tweet widget, a Vimeo video. When discovery succeeds, the response includes a new iframe field with HTML and any required scripts.This is the right path when the goal is the experience the source provides: playable media, interactive widgets, or anything that is not just a thumbnail and title. If you want a wrapper component that handles the injection for you, see Embed SDK with
media='iframe'. If you want a styled card built from JSON, see metadata API + custom HTML.What the iframe field returns
The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw' URL with 'iframe' API parameter:
CLI Microlink API example
microlink https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw&iframecURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw" \
-d "iframe=true"JavaScript Microlink API example
import createClient from 'microlink.io'
const microlink = createClient()
const { html } =
await microlink.embed('https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw')Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
"iframe": "true"
}
response = requests.get(url, params=querystring)
print(response.json())Ruby Microlink API example
require 'uri'
require 'net/http'
base_url = "https://api.microlink.io/"
params = {
url: "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
iframe: "true"
}
uri = URI(base_url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
"iframe" => "true"
];
$query = http_build_query($params);
$url = $baseUrl . '?' . $query;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET"
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #: " . $err;
} else {
echo $response;
}Golang Microlink API example
package main
import (
"fmt"
"net/http"
"net/url"
"io"
)
func main() {
baseURL := "https://api.microlink.io"
u, err := url.Parse(baseURL)
if err != nil {
panic(err)
}
q := u.Query()
q.Set("url", "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw")
q.Set("iframe", "true")
u.RawQuery = q.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}import createClient from 'microlink.io'
const microlink = createClient()
const { html } =
await microlink.embed('https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw')The discovered iframe is rendered above. The response payload contains the markup that produced it.
The
iframe object has two subfields:{
"iframe": {
"html": "<iframe width=\"100%\" height=\"152\" src=\"https://open.spotify.com/embed/track/3BovdzfaX4jb5KFQwoPfAw?utm_source=oembed\" ...></iframe>",
"scripts": []
}
}html— the markup to inject into the page.scripts— an array of{ src, async, charset }entries that some providers need. Empty for most video and audio providers; populated for Twitter, Instagram, and other widget-based embeds.
Inject the iframe HTML
The simplest pattern: fetch the data server-side, pass
iframe.html to the client, and inject it.Vanilla JavaScript
import createClient from 'microlink.io'
const microlink = createClient()
const embed = await microlink.embed(url)
if (embed) {
document.getElementById('embed').innerHTML = embed.html
embed.scripts.forEach(({ src, async, charset }) => {
if (document.querySelector(`script[src="${src}"]`)) return
const script = document.createElement('script')
script.src = src
if (async) script.async = true
if (charset) script.charset = charset
document.head.appendChild(script)
})
}The script step is what makes Twitter, Instagram, and similar widgets actually render — without it you get unstyled blockquotes.
React
import { useEffect, useState } from 'react'
import createClient from 'microlink.io'
const microlink = createClient()
function ProviderEmbed ({ url }) {
const [iframe, setIframe] = useState(null)
useEffect(() => {
let cancelled = false
microlink.embed(url).then(embed => {
if (cancelled) return
setIframe(embed)
embed?.scripts?.forEach(({ src, async, charset }) => {
if (document.querySelector(`script[src="${src}"]`)) return
const s = document.createElement('script')
s.src = src
if (async) s.async = true
if (charset) s.charset = charset
document.head.appendChild(s)
})
})
return () => { cancelled = true }
}, [url])
if (!iframe) return null
return <div dangerouslySetInnerHTML={{ __html: iframe.html }} />
}For React, the Embed SDK already handles this — see Embed SDK and pass
media="iframe".Server-side rendering
If you SSR the page, write the HTML and the script tags directly into the response — no client fetch needed:
const escapeHtml = value =>
String(value).replace(/[&<>"']/g, char => `&#${char.charCodeAt(0)};`)
const { title } = await microlink.metadata(url)
const { html, scripts } = await microlink.embed(url)
res.send(`
<article>
<h1>${escapeHtml(title)}</h1>
${html}
${scripts.map(s => `<script async src="${escapeHtml(s.src)}"></script>`).join('')}
</article>
`)When to use iframe vs embed SDK vs custom HTML
| If you want | Use |
|---|---|
| The provider's real interactive player or widget | iframe parameter (this page) |
| A drop-in component with fetching, lazy-loading, and theming | Embed SDK with media="iframe" |
| A static rich card, fully styled by you | metadata API + custom HTML |
The Embed SDK and the iframe parameter are not alternatives — the Embed SDK consumes the same
iframe field internally when you set media="iframe". Pick the Embed SDK if you want the wrapping component to also handle the loading state, lazy-loading, and CSS theming. Pick the raw iframe parameter if you want the markup and nothing else.Customize the iframe with oEmbed options
The iframe parameter accepts an object that forwards consumer options to the oEmbed endpoint:
The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw' URL with 'iframe' API parameter:
CLI Microlink API example
microlink https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw&iframe.maxWidth=350cURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw" \
-d "iframe.maxWidth=350"JavaScript Microlink API example
import createClient from 'microlink.io'
const microlink = createClient()
const { html } = await microlink.embed('https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw', {
maxWidth: 350
})Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
"iframe.maxWidth": "350"
}
response = requests.get(url, params=querystring)
print(response.json())Ruby Microlink API example
require 'uri'
require 'net/http'
base_url = "https://api.microlink.io/"
params = {
url: "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
iframe.maxWidth: "350"
}
uri = URI(base_url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
"iframe.maxWidth" => "350"
];
$query = http_build_query($params);
$url = $baseUrl . '?' . $query;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET"
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #: " . $err;
} else {
echo $response;
}Golang Microlink API example
package main
import (
"fmt"
"net/http"
"net/url"
"io"
)
func main() {
baseURL := "https://api.microlink.io"
u, err := url.Parse(baseURL)
if err != nil {
panic(err)
}
q := u.Query()
q.Set("url", "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw")
q.Set("iframe.maxWidth", "350")
u.RawQuery = q.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}import createClient from 'microlink.io'
const microlink = createClient()
const { html } = await microlink.embed('https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw', {
maxWidth: 350
})Each provider chooses which options it honors.
maxWidth and maxHeight are the most widely supported.See the oEmbed specification for the full list of consumer parameters.
When iframe discovery fails
Not every URL has an oEmbed endpoint. If discovery fails, the
iframe field is absent from the response — the rest of the metadata is still returned.Plan your code for both shapes:
const embed = await microlink.embed(url)
if (embed) {
container.innerHTML = embed.html
} else {
// fall back to a custom card built from title / image / description
container.innerHTML = renderCard(await microlink.metadata(url))
}The full provider list lives in the iframe parameter reference — 280+ providers including YouTube, Spotify, Twitter/X, Vimeo, Instagram, TikTok, Figma, CodeSandbox, CodePen, Reddit, Pinterest, Behance, Dribbble, TED, SoundCloud, and Mixcloud.
Pair iframe with metadata in one call
You usually want both — the iframe for playback, the metadata for the surrounding card frame:
The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw' URL with 'iframe' & 'palette' API parameters:
CLI Microlink API example
microlink https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw&iframe&palettecURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw" \
-d "iframe=true" \
-d "palette=true"JavaScript Microlink API example
import createClient from 'microlink.io'
const microlink = createClient()
const { html } =
await microlink.embed('https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw')
const { image, logo } = await microlink.metadata('https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw', {
palette: true
})Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
"iframe": "true",
"palette": "true"
}
response = requests.get(url, params=querystring)
print(response.json())Ruby Microlink API example
require 'uri'
require 'net/http'
base_url = "https://api.microlink.io/"
params = {
url: "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
iframe: "true",
palette: "true"
}
uri = URI(base_url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw",
"iframe" => "true",
"palette" => "true"
];
$query = http_build_query($params);
$url = $baseUrl . '?' . $query;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET"
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #: " . $err;
} else {
echo $response;
}Golang Microlink API example
package main
import (
"fmt"
"net/http"
"net/url"
"io"
)
func main() {
baseURL := "https://api.microlink.io"
u, err := url.Parse(baseURL)
if err != nil {
panic(err)
}
q := u.Query()
q.Set("url", "https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw")
q.Set("iframe", "true")
q.Set("palette", "true")
u.RawQuery = q.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}import createClient from 'microlink.io'
const microlink = createClient()
const { html } =
await microlink.embed('https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw')
const { image, logo } = await microlink.metadata('https://open.spotify.com/track/3BovdzfaX4jb5KFQwoPfAw', {
palette: true
})One request returns the player, the title and description, the publisher logo, and brand colors — enough to render a full provider-styled card.
This is also why the Embed SDK works the way it does: it requests
iframe, audio, video, image, logo together and picks the best media available per URL.Security and sandboxing
Injecting third-party HTML and scripts is intentional here — that is how the player renders. To reduce blast radius:
- Apply a strict Content Security Policy that allowlists only the providers you embed.
- Add
sandboxto the iframe element if you want to restrict navigation or popups. - Strip query parameters that could leak referrer data when privacy matters (use the
nocookievariants where the provider supports them, e.g.youtube-nocookie.com).
The HTML returned by Microlink mirrors what the provider hands out via oEmbed, so the security posture is the same as if you embedded the provider directly.
Next step
For a wrapper component that handles the iframe injection plus loading/lazy/theming for you, see Embed SDK.