Programmatically Discovering Sharing Code With oEmbed

The web is full of services that host rich content such as videos, images, music and podcasts, maps and graphs, and all manner of different delights. Chances are, when you add your content to a site, it will offer you a way to embed that content in a web page somewhere else.
Sites like YouTube have their own embeddable player that is popular to use in blog posts and even product pages.

Programmatically Discovering Sharing Code With oEmbed Leah Culver had while working on Pownce (a truly innovative social networking site that was the Betamax to Twitter’s VHS). Pownce wanted to embed rich representations of content into a user’s update stream, but didn’t want to limit support to only the services they’d specifically written code to integrate with. At dinner with colleague Mike Malone, as well as Cal Henderson (who led engineering at Flickr — one of the major providers of such content at the time) and Richard Crowley, they together hashed out an idea for an open standard for getting embed code from a URL. Henderson went away and drafted something up based on the discussion, and oEmbed was born.

Using oEmbed

Here’s how it works.

It starts with the URL that points to a single item of content. That might be a YouTube video, an image, or whatever. Typically this will have been provided by a user of your site or app as part of some content they wish to publish. The first step is to fetch the content of the page at that URL, which should be an HTML page.

If the site hosting the content supports oEmbed, in the <head> section of that page there should be a link element with an oembed content type:

<link rel="alternate" type="application/json+oembed" href="" title="Inclusive Components with Heydon Pickering" />

A note about XML: oEmbed supports responses in both XML and JSON format. For this article, I’m only considering JSON, because we’re not savages. If you’re in the unfortunate position to need to work with XML, be aware that it is a supported format with the oEmbed spec, although you may find that some providers only offer JSON responses.

This link tag as the rel attribute set to alternate and a type set to either application/json+oembed or text/xml+oembed. It’s this attribute that clues us into the fact that the URL given in the href is actually an oEmbed API endpoint for retrieving the details of the content.

That URL will have usually two parameters: url and format.

Parameter Value
url (required) The URL-encoded web address of the content item
format The format you’d like the response in. One of either json or xml

Common URL parameters for the initial consumer request

The full specification goes into much more detail here (and you should reference that if creating your own implementation) but these are the two parameters you’ll likely see the most.

So, we’ve got a URL, fetched the page, found an oEmbed link tag with another URL for an API endpoint. Next, we request that new URL, and that returns all the information the service has to provide about that piece of content.

{ "author_name": "Smashing Magazine", "width": 480, "title": "Smashing TV: Inclusive Components with Heydon Pickering (Nov 7th 2019)", "provider_name": "YouTube", "height": 270, "html": "<iframe width=\"480\" height=\"270\" src=\"\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>", "provider_url": "", "thumbnail_url": "", "type": "video", "thumbnail_height": 360, "author_url": "", "version": "1.0", "thumbnail_width": 480

Now we’re talking! The response gives us lots of information about the content. The version should for the foreseeable future be 1.0, which is the current version of the oEmbed spec. The other information returned depends largely on the value of type.

Response Types

The value of the type key in the response tells you what sort of media you’re going to be embedding.

Value of type What to expect
photo A static photo that offers a url, width and height that can be used for a basic img tag
video A video player, with html specifying the code required to embed a player on a page, although with a width and height
link The best way to deal with this content is just to provide a link after all. The response might have other useful information like a title, but it should just be linked up.
rich Some sort of rich content player, which just like the video type returns html, width and height

Aside from dedicated video content, the more common type you’re likely to see in the wild is rich. Even Flickr itself, while still sending a photo response, also supplies html for a rich embeddable ‘player’ for the image, too.

Most of the time, embedding the content in your site is just a case of using the code provided as the html value.

A Note On Security

One thing you might be rightly cautious of is taking an HTML response and embedding it programmatically into a page you host. Without the human step to double-check the code you’re pasting in, there is always potential for that code to be malicious. As such you should take appropriate steps to mitigate the risk.

That might include filtering the URLs to make sure the schemes and domains match those expected, and sandboxing code into an iframe on a different, cookieless domain. You should access the situation in which you’re using the code and make sure that you’re not exposing your self to undue risk.

Getting Started

As important as it is to understand the process when using oEmbed, the reality is that most common languages have libraries available that abstract away the process and make it relatively simple.

For example, the npm packaged oembed provides a very simple interface for making a request based on the content URL and getting the oEmbed response back in return.

First install the package into your project:

npm i oembed

And then request the URL. Here I’m using the URL of a presentation on Notist that I gave about oEmbed. How very meta.

const oembed = require('oembed');
const url = ''; oembed.fetch(url, { maxwidth: 1920 }, function(error, result) { if (error) console.error(error); else console.log("oEmbed result", result);

And the response:

{ type: 'rich', version: '1.0', title: 'Understanding oEmbed', author_name: 'Drew McLellan', author_url: '', provider_name: 'Notist', provider_url: '', cache_age: 604800, thumbnail_url: '', thumbnail_width: 1600, thumbnail_height: 900, html: '<p data-notist="drewm/ZOFFfI">View <a href="">Understanding oEmbed</a> on Notist.</p><script async src=""></script>', width: 960, height: 540 }

If you wanted to do the same in PHP, a handy package called embed/embed is available to install via Composer.

composer require embed/embed

And then in your PHP project:

use Embed\Embed; $info = Embed::create(''); $info->title; // "Understanding oEmbed"
$info->authorName; // "Drew McLellan
$info->code; // "<p data-notist="drewm/ZOFFfI"> ... </script>"

As you can see, with the use of a library the process becomes very simple and you can quickly get from a URL to the embed code, ready to show a rich representation of the user’s content.


oEmbed is a very elegant solution to a very specific problem. You’d be forgiven for thinking that only a few engineers working on big social networks would benefit from this, but in reality, publishing systems where a user might enter a URL are surprisingly common. Find me one back-end engineer who at some point hasn’t needed to build some kind of CMS. We may not think of it in the same terms, but if you accept user input, you should be thinking about what to do if that input contains URLs.

Now that you know about oEmbed (sorry) you’ve got no excuse not to give some serious consideration to how you handle URLs in your future projects.

  • oEmbed specification
  • oembed for NodeJS
  • embed/embed for PHP
  • “Announcing OEmbed: An Open Standard for Embedded Content,” Leah Culver
Smashing Editorial (ra, il)

Posted by Web Monkey