1. General

Note: the docs contain some opinions. You can treat them as "best practices" for working with embeds if you'd like. Of course, they are still just our opinions.

Different types of embeds

On the highest level there are two types of embeds: oEmbed and "regular embed". What they are and how they differ is this: oEmbed is (or should be) specifically crafted by the website owners to look optimal for that website; good examples are Twitter and Facebook. In reality, oEmbeds come in all sizes and shapes and often may be far from optimal.

Regular embeds, however, will look uniform across the field. Note, that "regular embed" is not an official term. Instead, they cover everything else which is not an oEmbed. These comprise of The Open Graph protocol and web scraping techniques. Regular embeds are divided further into different content types; more on that in a bit.

Because of the issues with oEmbeds and the uniform characteristics of other regular embeds we recommend to avoid using oEmbeds. Our example code on the bottom of this page will have an implementation which reflects this. Note also that our API will return both oEmbed and regular embed in the response, whenever available. The regular embed should be available for most of the time, while oEmbed may or may not be.

Security

oEmbeds have other problems as well — namely, the security isn't great. As it stands, oEmbed can contain any markup and thus injecting that into your site isn't safe, unless you really can trust the site. The safest way to present an oEmbed is to serve it in an iframe. Some sites (Twitter, Facebook) can probably be trusted, and serving them directly without an iframe should be OK.

There are other security consideration as well and this one applies to regular embeds: Linking to 3rd party images directly opens up Cross-Site Request Forgery (CSRF) and other vulnerabilities, and it's advisable to host all the images (including favicons) through a your own domain. That domain can be called, for example, safe.yourdomain.com, and it should be setup as a reverse proxy with NGINX to host the images. We will provide a sample NGINX configuration for that.

2. API

Request

The API is simple; you will issue a GET request to our url, and will get a JSON document as a response. The API endpoint is as follows:

https://api.embed.rocks/api/?url=<url>&key=<key>

The supplied url should be urlencoded. <key> is your API key (you'll find it in Dashboard).

Response

As a response, you will get a JSON document with relevant data fields. Depending on the type of webpage you will get a different types of responses, as explained below:

Common fields

There are a few fields that are common to all responses. These are:

NameValue
typerich | video | audio | photo
urlThe url you provided
oembedThe oembed data as such

Different types (rich, video, audio, photo) of responses have different fields, as show below:

type: rich

These are probably the most common types of responses. This indicates, that the page contains text + images (although it may contain only text too).

Note, the value can contain {...} which represents a JSON document. The value can also contain [...] which represents an array. An array can contain {...} (JSON documents).

Also note that the argument safe is for displaying the image safely and securely – we will provide sample NGINX configuration for this.

NameValue
typerich
urlThe url you provided
sitehostname of the site (www.example.com)
titleTitle of the page
descriptionA short (250 characters) snippet of text; best describing the page
articleThe whole article
favicon{
  • url: url of the favicon
  • safe: the same url as urlencoded component
}
images[ {
  • url: url of the image
  • safe: the same url as urlencoded component
} ]

type: video

NameValue
typevideo
urlThe url you provided
sitehostname of the site (www.example.com)
titleTitle of the page
descriptionA short (250 characters) snippet of text; best describing the page
favicon{
  • url: url of the favicon
  • safe: the same url as urlencoded component
}
videos[ {
  • url: url of the video
  • safe: the same url as urlencoded component
  • type: content-type of the video
} ]

Note that we return videos of content type text/html and application/flash if the site has told us that they are videos. Thus, we treat them as videos.

type: audio

NameValue
typeaudio
urlThe url you provided
sitehostname of the site (www.example.com)
titleTitle of the page
descriptionA short (250 characters) snippet of text; best describing the page
favicon{
  • url: url of the favicon
  • safe: the same url as urlencoded component
}
audios[ {
  • url: url of the audio
  • safe: the same url as urlencoded component
} ]

type: photo

NameValue
typephoto
urlThe url you provided
images[ {
  • url: url of the audio
  • safe: the same url as urlencoded component
} ]

3. Examples

3.1 A rich type

The rich type is probably the most common type; it contains usually an image and some text. The URL http://edition.cnn.com/2017/01/05/aviation/safest-airlines-for-2017/index.html will get us the following JSON document:

{
	"article": "<div>(article omitted in the example)</div>",
	"description": "AirlineRatings.com declares 2016 one of the safest years in aviation history as it names what it says are the world's safest airlines.",
	"favicon": {
		"safe": "http%3A%2F%2Fedition.cnn.com%2Ffavicon.ie9.ico",
		"url": "http://edition.cnn.com/favicon.ie9.ico"
	},
	"images": [
		{
			"safe": "http%3A%2F%2Fi2.cdn.cnn.com%2Fcnnnext%2Fdam%2Fassets%2F160412104516-airplane-generic-ii-super-tease.jpg",
			"url": "http://i2.cdn.cnn.com/cnnnext/dam/assets/160412104516-airplane-generic-ii-super-tease.jpg"
		}
	],
	"site": "CNN",
	"title": "The world's safest airlines for 2017?",
	"type": "rich",
	"url": "http://edition.cnn.com/2017/01/05/aviation/safest-airlines-for-2017/index.html",
	"videos": []
}

It will look like this when rendered (you render this yourself, so this is just an example):

3.2 An URL from YouTube.com

Here we will see a type of video — the videos array will contain items. The videos array will be sorted roughly in the order of preference — the most preferrable type are first. These would be "HTML5" videos. Flash videos would be less preferrable and they would be placed in the end of the array. Our example code will handle these correctly.

{
	"article": "<div><p>\n    <strong>Pour évaluer une vidéo, vous devez la louer.</strong>\n  </p></div>",
	"description": "A few pointers from my experience on things one should either do or avoid while in Finland. So some Finnish do's and don'ts! :) *On a side note, I know I hav...",
	"favicon": {
		"safe": "https%3A%2F%2Fs.ytimg.com%2Fyts%2Fimg%2Ffavicon-vflz7uhzw.ico",
		"url": "https://s.ytimg.com/yts/img/favicon-vflz7uhzw.ico"
	},
	"html": "<div class=\"card\">\n    <iframe style=\"width: 720px; height: 405px\" src=\"https://www.youtube.com/embed/9N0HB8vMJrI\"></iframe>\n    \n    <div class=\"card-text\">\n      <h3>Do's and Don'ts in Finland | KatChats</h3>\n      <p>A few pointers from my experience on things one should either do or avoid while in Finland. So some Finnish do's and don'ts! :) *On a side note, I know I hav...</p>\n      \n        <p class=\"fav\">\n          <img onerror=\"this.style.display='none'\" class=\"favicon\" src=\"https://s.ytimg.com/yts/img/favicon-vflz7uhzw.ico\">\n          YouTube\n        </p>\n    </div>\n  \n  </div>",
	"images": [
		{
			"safe": "https%3A%2F%2Fi.ytimg.com%2Fvi%2F9N0HB8vMJrI%2Fmaxresdefault.jpg",
			"url": "https://i.ytimg.com/vi/9N0HB8vMJrI/maxresdefault.jpg"
		}
	],
	"oembed": {
		"author_name": "KatChats",
		"author_url": "https://www.youtube.com/user/adamLsidney",
		"height": 270,
		"html": "<iframe width=\"480\" height=\"270\" src=\"https://www.youtube.com/embed/9N0HB8vMJrI?feature=oembed\" frameborder=\"0\" allowfullscreen></iframe>",
		"provider_name": "YouTube",
		"provider_url": "https://www.youtube.com/",
		"thumbnail_height": 360,
		"thumbnail_url": "https://i.ytimg.com/vi/9N0HB8vMJrI/hqdefault.jpg",
		"thumbnail_width": 480,
		"title": "Do's and Don'ts in Finland | KatChats",
		"type": "video",
		"version": "1.0",
		"width": 480
	},
	"site": "YouTube",
	"title": "Do's and Don'ts in Finland | KatChats",
	"type": "video",
	"url": "https://www.youtube.com/watch?v=9N0HB8vMJrI",
	"videos": [
		{
			"height": "720",
			"secureUrl": "https://www.youtube.com/embed/9N0HB8vMJrI",
			"type": "text/html",
			"url": "https://www.youtube.com/embed/9N0HB8vMJrI",
			"width": "1280"
		},
		{
			"height": "720",
			"secureUrl": "https://www.youtube.com/v/9N0HB8vMJrI?version=3&autohide=1",
			"type": "application/x-shockwave-flash",
			"url": "http://www.youtube.com/v/9N0HB8vMJrI?version=3&autohide=1",
			"width": "1280"
		},
		{
			"height": "720",
			"type": "text/html",
			"url": "https://www.youtube.com/embed/9N0HB8vMJrI",
			"width": "1280"
		}
	]
}

3.3 An URL from Twitter.com

Here we can decide if we want to render this as an oEmbed or a regular embed, because the JSON contains both. Below you can see how it looks like when rendered in both ways.

{
	"article": "<div><p>\n      Twitter may be over capacity or experiencing a momentary hiccup. <a href=\"#\">Try again</a> or visit <a href=\"http://status.twitter.com\">Twitter Status</a> for more information.\n    </p></div>",
	"description": "“to understand the pillow, one must become the pillow”",
	"favicon": {
		"safe": "https%3A%2F%2Fabs.twimg.com%2Ffavicons%2Ffavicon.ico",
		"url": "https://abs.twimg.com/favicons/favicon.ico"
	},
	"html": "<div class=\"card\">\n    <a target=\"_blank\" href=\"https://twitter.com/EmrgencyKittens/status/817189457476648960\">\n      \n    <img onerror=\"this.style.display='none'\" class=\"card-image\" src=\"https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FC1c9erlWgAAUhEO.jpg%3Alarge\">\n  \n      \n    <div class=\"card-text\">\n      <h3>Emergency Kittens on Twitter</h3>\n      <p>“to understand the pillow, one must become the pillow”</p>\n      \n        <p class=\"fav\">\n          <img onerror=\"this.style.display='none'\" class=\"favicon\" src=\"https://abs.twimg.com/favicons/favicon.ico\">\n          Twitter\n        </p>\n    </div>\n  \n    </a>\n    </div>",
	"images": [
		{
			"safe": "https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FC1c9erlWgAAUhEO.jpg%3Alarge",
			"url": "https://pbs.twimg.com/media/C1c9erlWgAAUhEO.jpg:large"
		}
	],
	"oembed": {
		"author_name": "Emergency Kittens",
		"author_url": "https://twitter.com/EmrgencyKittens",
		"cache_age": "3153600000",
		"height": null,
		"html": "<blockquote class=\"twitter-tweet\"><p lang=\"en\" dir=\"ltr\">to understand the pillow, one must become the pillow <a href=\"https://t.co/UUqd0uJQht\">pic.twitter.com/UUqd0uJQht</a></p>&mdash; Emergency Kittens (@EmrgencyKittens) <a href=\"https://twitter.com/EmrgencyKittens/status/817189457476648960\">January 6, 2017</a></blockquote>\n<script async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>",
		"provider_name": "Twitter",
		"provider_url": "https://twitter.com",
		"type": "rich",
		"url": "https://twitter.com/EmrgencyKittens/status/817189457476648960",
		"version": "1.0",
		"width": 550
	},
	"site": "Twitter",
	"title": "Emergency Kittens on Twitter",
	"type": "rich",
	"url": "https://twitter.com/EmrgencyKittens/status/817189457476648960",
	"videos": []
}

Here is the oEmbed rendering:

And here the regular:

4. Example code

We promised to provide you with sample code for rendering and NGINX, so here it is:

Here is a sample Mustache template for rendering all types of cards. It should be easy enough to convert into any other types of templates: card.mustache

Here are the JavaScript (CoffeeScript) functions that this template uses: card.coffee

Here is the CSS and Stylus codes for the cards: card.css, card.styl

Here is the sample NGINX configuration for safe & secure images. Note that this has SSL (Let's Encrypt) enabled, which you can turn off: safe.conf