Skip to content

Instantly share code, notes, and snippets.

@hakanai
Created April 9, 2026 09:11
Show Gist options
  • Select an option

  • Save hakanai/cca7a92a902a9a1a39b347aa37258abc to your computer and use it in GitHub Desktop.

Select an option

Save hakanai/cca7a92a902a9a1a39b347aa37258abc to your computer and use it in GitHub Desktop.
oEmbed notes

oEmbed notes

oEmbed is the format used to embed content from a website into other sites or apps.

It is not the only standardized format for this. Including an application/ld+json summary in the page header is another.

How it works

  1. Consumer determines that the site supports oEmbed. There are several ways:

    1. Optionally, the oEmbed provider registry lists all oEmbed providers. It is maintained at their GitHub project.

    2. The webpage itself can link to the endpoint:

      <link type="application/json+oembed"
            href="https://flickr.com/services/oembed?url=http%3A%2F%2Fflickr.com%2Fphotos%2Fbees%2F2362225867%2F&format=json"
            rel="alternate" title="Flickr oEmbed Profile" />
      <link type="text/xml+oembed"
            href="https://flickr.com/services/oembed?url=http%3A%2F%2Fflickr.com%2Fphotos%2Fbees%2F2362225867%2F&format=xml"
            rel="alternate" title="Flickr oEmbed Profile" />

      Or it might be in the Link header, specified by RFC 8288:

      Link: <https://flickr.com/services/oembed?url=http%3A%2F%2Fflickr.com%2Fphotos%2Fbees%2F2362225867%2F&format=json>; rel="alternate"; type="application/json+oembed"; title="Flickr oEmbed Profile"
      Link: <https://flickr.com/services/oembed?url=http%3A%2F%2Fflickr.com%2Fphotos%2Fbees%2F2362225867%2F&format=xml>; rel="alternate"; type="text/xml+oembed"; title="Flickr oEmbed Profile"
      
  2. Consumer makes a request to the oEmbed endpoint at http://www.flickr.com/services/oembed/?url=http%3A//www.flickr.com/photos/bees/2341623661/&format=json

  3. The provider (in this case, Flickr) responds (in this case, with JSON). See JSON below for an example.

  4. Consumer renders the embed. The options are:

    1. Take the html value from the response and include it, after sanitizing it to remove any potentially malicious code.

    2. Directly render the embed using the response parameters (much safer).

Standard request parameters

  • url
    • Required, pretty self-explanatory.
  • maxwidth, maxheight
    • Optional ints specifying the maximum size of the resource.
    • Only supported for resource types photo, video, and rich.
  • format
    • Optional string specifying a format (not sure why the Accept: header was not good enough).
    • See Standard formats
    • Sometimes specified by appending .json, .xml, etc. to the endpoint instead. (If both are specified, the parameter is ignored.)

Standard response parameters

Required parameters

  • version
    • The oEmbed version, 1.0.
  • type
    • The resource type, one of:
      • photo
      • video
      • link
      • rich

Optional parameters

  • title

    • The resource's title.
    • Equivalent to dc:title.
  • author_name

    • The name of the resource's author.
    • Equivalent to dc:creator.
    • There are some strange code points in the documented example.
  • author_url

    • A URL identifying the resource's author.
    • Typically links to the author's profile on the site.
  • provider_name

    • The name of the resource provider.
    • Loosely equivalent to dc:publisher.
  • provider_url

    • A URL identifying the resource provider.
    • Typically links to the site root.
  • cache_age

    • The suggested cache lifetime for this resource, in seconds.
  • thumbnail_url

    • A URL pointing at a thumbnail image of the resource.
  • thumbnail_width, thumbnail_height

    • The size of the thumbnail specified by thumbnail_url.

Type-specific required parameters

  • width, height

    • The required size to display the embed, in pixels.
    • Required for types photo, video, and rich.
  • url

    • The URL of the image.
    • Required for type photo.
    • I assume it might occur on other resource types, but I haven't seen it.
  • html

    • The HTML to embed the resource.
    • Required for types video and rich.
    • Should be valid XHTML 1.0 Basic.
      • The spec says that the HTML should have no padding or margins, but CSS is what enforces that, and that isn't in control of the provider.
      • Also seen used with type photo, e.g., the Flickr example above.

Non-standard parameters seen in the wild

On Flickr

  • flickr_type: photo
    • Seems to be the same as the type, but must differ in some cases.
  • web_page: https://www.flickr.com/photos/bees/2341623661/
    • Seems to be the same URL as the url parameter.
  • web_page_short_url: https://flic.kr/p/4yVr8K
    • The equivalent short URL.
  • license_id: 0 (number)
    • Flickr's license ID. Some but not all IDs are documented.
  • license: All Rights Reserved
    • The name of the license.

On Vimeo

  • account_type: basic
  • description: Colombia - 2012\nOn my second holiday to(...truncated...)
  • duration: 239 (number)
  • is_plus: 0
  • thumbnail_url_with_play_button: https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F329159386-6b92d7eedabaa170ac5e1bcc98ba32dc473e7e8d79edfafaa1d5a14e4de6a967-d_295x166%3Fregion%3Dus&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png
  • upload_date: 2012-08-11 10:36:10
  • uri: /videos/47360546
  • video_id: 47360546 (number)

Standard formats

JSON

  • Parameter value: json
  • Content type: application/json+oembed
{
  "version": "1.0",
  "type": "photo",
  "flickr_type": "photo",

  "title": "ZB8T0193",
  "cache_age":3600,

  "width": 1024,
  "height": 683,
  "url": "https:\/\/live.staticflickr.com\/3123\/2341623661_7c99f48bbf_b.jpg",

  "thumbnail_width": 150,
  "thumbnail_height": 150,
  "thumbnail_url": "https:\/\/live.staticflickr.com\/3123\/2341623661_7c99f48bbf_q.jpg",

  "web_page":"https:\/\/www.flickr.com\/photos\/bees\/2341623661\/",
  "web_page_short_url":"https:\/\/flic.kr\/p\/4yVr8K",

  "author_name": "\u202e\u202d\u202cbees\u202c",
  "author_url":"https:\/\/www.flickr.com\/photos\/bees\/",

  "provider_name": "Flickr",
  "provider_url": "https:\/\/www.flickr.com\/"

  "license": "All Rights Reserved",
  "license_id": 0,

  "html": "<a data-flickr-embed=\"true\" href=\"https:\/\/www.flickr.com\/photos\/bees\/2341623661\/\" title=\"ZB8T0193 by \u202e\u202d\u202cbees\u202c, on Flickr\"><img src=\"https:\/\/live.staticflickr.com\/3123\/2341623661_7c99f48bbf_b.jpg\" width=\"1024\" height=\"683\" alt=\"ZB8T0193\"><\/a><script async src=\"https:\/\/embedr.flickr.com\/assets\/client-code.js\" charset=\"utf-8\"><\/script>",
}

XML

  • Parameter value: xml
  • Content type: text/xml+oembed
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<oembed>
    <version>1.0</version>
    <type>photo</type>
    <flickr_type>photo</flickr_type>

    <title>ZB8T0193</title>
    <cache_age>3600</cache_age>

    <width>1024</width>
    <height>683</height>
    <url>https://live.staticflickr.com/3123/2341623661_7c99f48bbf_b.jpg</url>

    <thumbnail_width>150</thumbnail_width>
    <thumbnail_height>150</thumbnail_height>
    <thumbnail_url>https://live.staticflickr.com/3123/2341623661_7c99f48bbf_q.jpg</thumbnail_url>

    <web_page>https://www.flickr.com/photos/bees/2341623661/</web_page>
    <web_page_short_url>https://flic.kr/p/4yVr8K</web_page_short_url>

    <author_name>&#x202e;&#x202d;&#x202c;bees&#x202c;</author_name>
    <author_url>https://www.flickr.com/photos/bees/</author_url>

    <provider_name>Flickr</provider_name>
    <provider_url>https://www.flickr.com/</provider_url>

    <license>All Rights Reserved</license>
    <license_id>0</license_id>

    <html>&lt;a data-flickr-embed="true" href="https://www.flickr.com/photos/bees/2341623661/" title="ZB8T0193 by &#x202e;&#x202d;&#x202c;bees&#x202c;, on Flickr"&gt;&lt;img src="https://live.staticflickr.com/3123/2341623661_7c99f48bbf_b.jpg" width="1024" height="683" alt="ZB8T0193"&gt;&lt;/a&gt;&lt;script async src="https://embedr.flickr.com/assets/client-code.js" charset="utf-8"&gt;&lt;/script&gt;</html>
</oembed>

Quirks

The spec insists on using CDATA for XML

The spec specifically calls out that PCDATA should be used for the content of the <html> element.

As <html> necessarily includes XML tags, CDATA would have been one of the better ways to escape the content, but they must have their reasons. (The best way to embed it would have been namespacing the elements!)

It's especially odd because the spec also chooses XHTML 1.0 Basic, an XML format which would otherwise permit them.

Strange code points

When you let people choose their own usernames, sometimes people will insert Unicode formatting characters into their usernames to make it render in a different direction. This allows people to trick others into thinking they have a different name.

To thwart this, you will usually do something like this:

Username: <span style="direction:ltr; unicode-bidi:bidi-override">{name}</span>    

Or you might use some of the Unicode code points that give the same behavior without adding any HTML:

  • U+200E Left-to-Right Mark (LRM)
  • U+200F Right-to-Left Mark (RLM)
  • U+202A Left-to-Right Embedding (LRE)
  • U+202B Right-to-Left Embedding (RLE)
  • U+202C Pop Directional Formatting (PDF)
  • U+202D Left-to-Right Override (LRO)
  • U+202E Right-to-Left Override (RLO)
  • U+2066 Left-to-Right Isolate (LRI)
  • U+2067 Right-to-Left Isolate (RLI)
  • U+2068 First Strong Isolate (FSI)
  • U+2069 Pop Directional Isolate (PDI)

The behavior of these is documented in UAX #9.

But what's odd is that the sequence is like this:

"‮‭‬{name}‬"

RLOLROPDF{name}PDF

But when just trying to reverse the name, this is fine:

"‮{name}‬"

RLO{name}PDF

It isn't something Flickr is doing for all usernames, but rather, this one user has an odd name. Nonetheless, this URL is given in the actual oEmbed docs, so it's something people will definitely discover for themselves.

It seems that it is not their display username, as you can see their display name in the application/ld+json data inside the same page. It is also not the bare user ID, which you can see in all the URLs. Flickr, as seen in the page source, has at least four distinct usernames.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment