An API for the Web: Learning YQL

An API for the Web: Learning YQL

The Yahoo Query Language is a great tool that’s guaranteed to speed up your web development time. The more complex your project, the more time YQL will save you. So, is it a framework, an application, a beverage? Today, you’ll find out what it is and how to use it!

Prefer a Video Tutorial? Join Plus!

If you’re more of a visual learner, you can watch a video version of this article instead. Simply help give back to Nettuts+ by signing up for a Plus membership, which grants you access to the Plus content for ALL of our sites – all for $19 per month.

Already a Member?

Watch the video version of this tutorial.

What is YQL?

Web apps and web services multiply like rabbits. They’re all fun to play with (like rabbits) and fun to integrate into other projects (unlike rabbits). But learning a new API every other day isn’t feasible or fun. And that’s the problem the Yahoo Query Language (YQL) is out to solve.

Think of YQL as the API for the web, the one API to rule them all. It’s not a hard one to learn, so let’s get you up to speed right now!

How do I use it?

Yahoo has put together a pretty nice console for us to flex our muscles with YQL. Load up that console, and let’s explore it.

In the right sidebar, you can choose a “table” in the “database”; a sample query will show up in the statement box at the top. To the right of the statement box, you can see what the corresponsing REST query would. Below, you have the data returned from the query; you can receive data in either XML or JSON.

So, let’s try a query!

select * from flickr.photos.interestingness(20)

Here’s one of the sample queries; This will return twenty images from the Flickr’s interestingness group. The results of the query look like this:

Let’s try another one.

select * from feed where url='http://rss.news.yahoo.com/rss/topstories'

This query returns each of the recent items in a feed, in this case, the Yahoo News Top Stories. Of course, we could handle it ourselves, but this will be quicker and easier.

You’ll notice that both these queries are for Yahoo sites; out of the box YQL only offers table for Yahoo properties. But they have made it extendable, and many people have written other tables. To get those, click the “Show Community Tables” in the sidebar. Now we can leverage everything from Netflix to the New York Times, from GitHub to Instapaper.

So how can we use YQL in our own projects? Most often, you’ll implement it using cURL, but we could do it in JavaScript as well. Let’s look at the cURL now, and what we get from it.

Let’s take that flickr interestingness query we just looked at; here’s what we do:

$query = 'select * from flickr.photos.interestingness(20)';

// insert the query into the full URL
$url = 'http://query.yahooapis.com/v1/public/yql?format=json&q=' . urlencode($query);

// set up the cURL
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, false);

// execute the cURL
$rawdata = curl_exec($c);
curl_close($c);

// Convert the returned JSON to a PHP object
$data = json_decode($rawdata);

// Show us the data
echo '<pre>';
print_r($data);
echo '</pre>';

It’s not too complicated; if you’ve not familiar with cURL, check out Burak Guzel’s great tut here on Nettuts earlier this month. We assign the cURL return value to $rawdata and then convert it to PHP. Calling the print_r function gives us these results.

As you can see, our $data object has one property: query. That property parents all the tasty bits. You can see from the $data->query->count that we received 20 objects, matching our query. But it’s $data->query->results that we’re really interested in; that’s where our data is. The results object has one array in it, called photos.

Armed with this information, we could display the twenty latest interesting photos from flickr (we would use the url http://www.flickr.com/photos/$owner/$id, taking those variable from each photo object.)

I should note here that not all queries will display their results in the same way; some aren’t quite as developer friendly as this one. It’s a good idea to use the YQL console (or just print_r) to check out the results format before proceeding.

So you’ve got an idea of what YQL is and how you can use it. Now, let’s use YQL in a small project!

Tuts+ Tweets

Let’s build a Twitter panel that will show the latest tweets from each of the Tuts+ sites’ Twitter accounts. We’ll start by going to the YQL console and looking at our options. Make sure you’re viewing the community tables. Under the Twitter section, choose twitter.user.profile (which will include the latest tweet), or type this query into the statement box:

select * from twitter.user.profile where id="nettuts"

As we can see from the results in the tree view, the object we’ll get back isn’t formatted quite as nicely as the Flickr ones; however, we’ll make it!

Let’s begin by replacing the Flickr query in the above example with this one. Here’s what we get:

What’s wrong? Since the twitter datatable isn’t one of Yahoo’s built-in tables, we need to tell YQL to use the community tables as well. How do we do that? We’ll add a the key/value env=store://datatables.org/alltableswithkeys to our base URL; now the $url variable should look like this:

$url = 'http://query.yahooapis.com/v1/public/yql?format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&q=' . urlencode($query);

Now if we try it …

We’ve got the twitter data!

Now that we’re successfully getting Nettuts’ twitter profile, let’s consider the others. We need to get the profiles of the following accounts:

  • Psdtuts
  • Vectortuts
  • Audiotuts
  • Aetuts
  • Activetuts
  • Cgtuts
  • Phototuts
  • Tutsplus

So do we need to do eight more cURLs to YQL to get all the data we need? Thankfully, YQL has our back here; we can use this:

SELECT * FROM query.multi where queries="QUERIES GO HERE"

Armed with this knowledge, we’re ready to build our widget. We’ll begin with an array of the twitter queries:

$twitter = array (
'tutsplus'   => 'SELECT * FROM twitter.user.profile WHERE id=\'tutsplus\'',
'nettuts'    => 'SELECT * FROM twitter.user.profile WHERE id=\'nettuts\'',
'phototuts'  => 'SELECT * FROM twitter.user.profile WHERE id=\'phototuts\'',
'audiotuts'  => 'SELECT * FROM twitter.user.profile WHERE id=\'audiotuts\'',
'psdtuts'    => 'SELECT * FROM twitter.user.profile WHERE id=\'psdtuts\'',
'aetuts'     => 'SELECT * FROM twitter.user.profile WHERE id=\'aetuts\'',
'cgtuts'     => 'SELECT * FROM twitter.user.profile WHERE id=\'cgtutsplus\'',
'vectortuts' => 'SELECT * FROM twitter.user.profile WHERE id=\'vectortuts\'',
'activetuts' => 'SELECT * FROM twitter.user.profile WHERE id=\'activetuts\''
);

Let’s create our full query now:

$query ='SELECT * FROM query.multi where queries="' . implode(';', $twitter) . '"';

Since it’s getting a bit complicated, we’ll put the root URL in its own variable, and then put everything together. Note that I added diagnostics=false to the root URL; this prevents YQL from returning a bit of extra data with our results. Why? It will just make it easier when we inspect the results in a moment.

$root = 'http://query.yahooapis.com/v1/public/yql?format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&diagnostics=false';
$url = $root . '&q=' . urlencode($query);

Now that we’ve got our complete URL, let’s create our cURL, just as we already did:

$c = curl_init();
 
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, false);

And like last time, we’ll catch the results, convery the JSON to a PHP object, and output them for inspection.

$data = json_decode(curl_exec($c));

curl_close($c);

echo '<pre>';
print_r($data);
echo '</pre>';

I won’t show them to you here, but you should be able to stroll through them and see the pieces of data we want to pull out. Notice that the results object has a results array inside it; that’s a bit unexpected, but I believe it has something to do with the fact that we’re executing multiple queries. When you’re done, head back to the PHP and create a $results variable (and don’t forget to remove the printr code):

$results = $data->query->results->results;

The HTML

Now that we’ve got our data, its time for some HTML. Let’s throw in a basic template under the PHP:

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Yahoo Query Language Introduction</title>
<link rel="stylesheet" href="default.css" />
</head>
<body>
<h1>The Tuts+ Network: Latest Tweet</h1>
<ul>
</ul>
</body>
</html>

Now, inside the list, we’ll use some PHP to iterate over each of the items in the $results array we extracted and build an entry for it. First, set up the loop:

<?php for ($i = 0; i$i < count($twitter); $i++) : ?>
	<li>

	</li>
<?php endfor; ?>

Inside that list item, open a PHP codeblock; we should begin by setting up a few variables.

	$meta = $results[$i]->item->meta; 
	$item = $results[$i]->item->item;
	$link = $results[$i]->item->resource;

Unfortunately, the author of the twitter table didn’t make the return object too easy to work with; instead of using key/value pairs, each key and value are entries in their own array. So it won’t be incredible obvious what we’re each object reference is when we’re done. However, remember that this is all subject to the author. The flickr table we looked at earlier—or the RSS table that you should check out—is a much more usable API.

So what do we want in our twitter widget? Let’s show the user avatar on the left and their name, username, latest tweet, and time of latest tweet on the right. To do so, let’s add this below those variables:

<?php echo "<a class='img' href='$link'><img src='" .$item[0]->resource ."' alt='" . $meta[0]->content ."' /></a>"; ?>
	<div>
		<?php echo "<a href='$link'>" .$meta[0]->content . "</a> "; ?>
		<small>(<?php echo $meta[1]->content ?>)</small>
		<small> <?php echo $item[1]->meta[2]->content; ?> </small>
		<?php echo '<a href="' . $item[1]->resource . '">' . $item[1]->meta[1]->content . '</a>'; ?>
	</div>

I know it’s a bit cryptic, but if you look at this and then look at the object we printed out to the browser, you’ll see that it works out nicely. We start with an anchor, and put the avatar image in it. After that, inside a div, we make another link for the name, which links to their twitter page. Then we put their username and time of last tweet in small tags (and if we wanted to, we could convert the time to something a little more viewer-friendly). Finally, we put their latest tweet in an anchor; cliking it will take you to the tweet’s page.

Here’s what this looks like:

Not pretty yet, but we’ve got some good hooks for our CSS.

The CSS

Nothing complicated here; we start by evening out the landscape:

body {
	font: 13px/1.5 'Helvetica Neue', Arial, 'Liberation Sans', FreeSans, sans-serif;
	background:#ececec;
	padding:10px;
}
img {
	border:0;
}

Then we’ll give out list its look and feel:

ul {
	margin:0;
	padding:0;
	border:1px solid #474747;
	border-radius:5px;
	-moz-border-radius:5px;
	-webkit-border-radius:5px;
	background:#ccc;
	width:50%;
}
li {
	min-height:50px;
	padding:10px 5px;
	list-style-type:none;
	border-bottom:1px solid #474747;
	border-top:1px solid #ececec;
}
li div {
	padding-left:58px;
}
li a.img {
	float:left;
	padding-right:5px;
}
li a {
	display:block;
}
li:first-child {
	border-radius:5px 5px 0 0;
	-moz-border-radius:5px 5px 0 0;
	-webkit-border-radius:5px 5px 0 0;
}
li:last-child {
	border-bottom:0;
}

As a final touch, we’ll give each list item a shadow on hover:

li:hover {
	box-shadow: 0px 0px 15px #000;
	-moz-box-shadow: 0px 0px 15px #000;
	-webkit-box-shadow: 0px 0px 15px #000;
}

There you have it! Behold our completed twitter widget:

Doing it with JavaScript

If you’d prefer, you can use jQuery to execute a YQL statement. You can get the plugin—called jquery.queryYQL—on GitHub. It’s pretty simple to use; here’s a modification of the example query:

$.queryYQL("select * from feed where url='http://feeds.feedburner.com/nettuts?format=xml'", function (data) {
	
	var ul = $("<ul/>");
	
	$.each(data.query.results.item, function () {
		$("<li/>").append(this.title).appendTo(ul);
	});
	
	ul.appendTo($("#content"));
});

Will you use it?

YQL is a pretty powerful tool; it should save you a lot of time by giving you a single, common API to access content all over the web. You really should browse through the list of available tables; you’ll probably find something that will same you a lot of time. Some tables even provide authentication and writing.

Is YQL a tool you’ll use in the future? Let me know in the comments!

Write a Plus Tutorial

Did you know that you can earn up to $600 for writing a PLUS tutorial and/or screencast for us? We’re looking for in depth and well-written tutorials on HTML, CSS, PHP, and JavaScript. If you’re of the ability, please contact Jeffrey at nettuts@tutsplus.com.

Please note that actual compensation will be dependent upon the quality of the final tutorial and screencast.

Write a PLUS tutorial

Tags: apiyql
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://twitter.com/KGTheNerd Karthik

    Awesome, I will try this out for sure :)

  • http://chadwik.us Chad

    Damn, I was going to write a tutorial on this. Great job!

  • Luisito

    Nice tut! thx man!

  • http://codesanity.net trs21219

    Hmm ive never heard of this before. pretty interesting though.

  • YoYo

    I´m fourth!!!!!!

    • http://www.nouveller.com/ Benjamin Reid

      But really, you’re last. ;)

  • http://phunky.co.uk Phunky

    YQL is awesome, i’ve been using it for ages on http://phunky.co.uk/LastFM/ and on my blog too.

    When you start using JOINs while scraping content from multiple sites is when you will see it’s true power :)

  • http://phunky.co.uk Phunky

    YQL is awesome, i’ve been using it for ages on http://phunky.co.uk/LastFM/ and on my blog too.

    When you start using JOINs while scraping content from multiple sites is when you will see it’s true power :)

    Also to simplify your examples you could have just used JSON-P and saved having to do anything server side.

  • http://www.airwolfe.com Alex Wolfe

    Wow, what a time save for people using Apis. This helps from having to search trough tons of documentation on other sites when your just trying to perform a simple request of information. Thanks for sharing!

  • Can****yon

    Like your job.

    Waiting you open a blog or something like that.
    Tank for that. ;-)

  • minimee

    would you please include the code as a package in this tutorial. thanks in advance

  • Brian Reindel

    Andrew, does YQL offer any sort of built-in caching mechanism, or is it up to the API implementer to cache the “table” results, and then offer some sort of a hook (like an additional ‘where’ clause) for the YQL statement? Also, if you don’t like someone’s XYZ API implementation, is it possible to write your own without namespace conflicts? For example, if someone wrote a table for Netflix, what if I want to write a table for Netflix — do I have to call the table something different?

    • http://www.rogerst Roger Stringer

      Caching is on your own.

      You can write your own API and just use the USE command to call it before doing the YQL queries

    • http://chadwik.us Chad

      You would have to cache the table results.

      It shouldn’t be problem on writing your own table. Check out this article by Christian Heilmann.

      http://24ways.org/2009/the-web-is-your-cms

    • http://php.net Peter C.

      With regards to namespace conflicts, you can either not include the conflicting table (e.g. if it’s from datatables.org; no luck if it’s a ‘core’ table) or just use your own namespace (e.g. reindel.netflix)

  • http://developer.yahoo.com/yql Jonathan Trevor

    Nice write-up. You might want to try using one of YQLs great features – joining across different web services or data sources – to get the same information rather than using the community multiquery table. Its more compact and faster. For example:

    SELECT * FROM twitter.user.profile WHERE id in (‘tutsplus’,'nettuts’,…)

    • http://php.net Peter C.

      I came to the comments area just to add that same note. IN can also be used with sub-selects, a feature I use very often. :)

    • http://andrewburgess.posterous.com Andrew Burgess
      Author

      Very cool! Thank for pointing that out; I wasn’t aware of it.

  • http://www.rogerstringer.com Roger Stringer

    Also, http://github.com/spullara/yql-tables has some useful YQL tables that you can build on.

  • http://wargraphicarts.com WAR

    Very useful!! Thanks!

  • http://yup.dk Hans

    That is pretty nice I must say.

  • http://360signals.com/ Maor Henry Hazan

    Amazing! Thank you for the awesome tutorial!

  • http://www.iMatt.si iMatt

    It`s awesome to be a PLUS user! I realy dont mind the 9$/month. The tuts are realy worth it! Keep on the good work Jeff and all the other authors! Greetz, Matt

  • http://www.quizzpot.com Crysfel

    Very nice!!

    • pablo

      crysfel que ha pasado con tu web?’

  • http://www.imblog.info Muhammad Adnan

    Thanks for adding Moneybookers option to be a Plus Member. I will definitely be a PLUS member soon.

    I am happy with this option of buying subscription. But not happy from jeff :(
    ( thats my personal feelings)

    • http://www.jeffrey-way.com Jeffrey Way

      I’m sorry you’re unhappy that I couldn’t use your tutorial – no matter how much I tried to work with you.

      • http://www.imblog.info Muhammad Adnan

        not fair :(

  • Webfreak05

    More frequent content for plus members..thank you, it’s totally awesome..Jeffrey..i’m missing wordpress tutorials..and please do more php tutorials..thanks alot Nettuts.

    Hey everyone..9 bucks a month is peanuts compared to the knowledge you learn here…i’m a subscriber and all i can say is that i’ve never been happier with my membership :)

  • http://eantz.co.cc Destiya Dian

    very interesting tuts..

  • http://spotdex.com/ David Moreen

    To many things to consume!

  • http://gilleshoarau.com Gilles Hoarau

    Yahoo got a great idea! Thanks Andrew for sharing that!

  • http://php.net Peter C.

    It would’ve been nice to have a brief mention of the HTML data table, and custom data tables, effectively allowing any web page or service to be consumed.

  • http://www.paulbaarn.nl Paul Baarn

    A great tutorial and something I’ll be trying very soon. The screencast is also very clear.

    Jeffrey, why don’t you go ahead and register TextExpander? hahaha

  • http://www.jordanwalker.net/index.php Jordan Walker

    That is great, wonder how this will all change with BING

  • Z

    Even though the video is fully buffered it won’t go past 9:31 for me no matter how many times I try to watch it!

    • http://www.jeffrey-way.com Jeffrey Way

      How strange. It’s working for me. You can always right-click and download the movie to your computer. :)

  • http://mokshasolutions.com Moksha

    Really Cool, YAHOO is bounce back as it was in 90′s I hope it make a big way back in all things it use to do.

    thanks for article

  • http://bloggerzbible.blogspot.com/ Bloggerzbible

    nice tutorial

  • http://www.fishmemory.net fractalbit

    This is excellent! And the video tutorial by Jeff super awesome! Since i am new to this, allow me a few questions.

    I want to bulid a basic vista/7 gadget that reads a feed and display the results. Can i use jquery and YQL to achieve this?

    Also, i would love if you could make a tutorial about building vista/7 gadgets. Since the technologies used are xml/html/javascript i believe it really has a place in this site.

    Thanks anyway!

  • http://sonergonul.com Soner Gönül

    That’s cool Thanks !

  • http://www.satya-weblog.com Satya Prakash

    I have expected few more use cases

  • http://www.markandey.com markandey
  • http://webkul.com vipin sahu

    Awesome explanation on YQL . Thanks :)

  • http://webkul.com vipin sahu

    how can we grab total no of buzz user using yql ?

  • cssn00b

    Hi, nice tutorial..
    but when we decode the json reply..
    its object..can we do it to an array ??
    I know OOP people will say, both are same :P .,
    but can we retrieve it to an array instead of object ??

    Thanks =)

  • Rob

    Hey I’m looking to do something similar with stocks, however when attempting to make a similar query, I get the following error:

    {“error”:{“lang”:”en-US”,”description”:”No definition found for Table query.multi”}}

    Here’s my code.. any idea why it’s not recognizing this? (I’m running it in Joomla)

    $stocks = array (
    ‘YHOO’ => ‘SELECT * FROM yahoo.finance.quotes where symbol=\’YHOO\”,
    ‘AAPL’ => ‘SELECT * FROM yahoo.finance.quotes where symbol=\’AAPL\”,
    ‘GOOG’ => ‘SELECT * FROM yahoo.finance.quotes where symbol=\’GOOG\”,
    ‘MSFT’ => ‘SELECT * FROM yahoo.finance.quotes where symbol=\’MSFT\”
    );

    $query = ‘USE “http://www.datatables.org/yahoo/finance/yahoo.finance.quotes.xml”;
    SELECT * FROM query.multi where queries=”‘ . implode(‘;’, $stocks) . ‘”‘;
    $root = ‘http://query.yahooapis.com/v1/public/yql?q=’;
    $url = $root . urlencode($query).’&format=json&diagnostics=false’;

    • Rob

      I’m going to answer my own message for those of you who are interested. I used a simple foreach loop! :)

  • Tahir Azeem Alvi

    Hi,

    are anybody know how call the YQL from action script 3 for fetch stock quotes, or anyone have reference
    URL?

    Thanks

  • http://www.blog.shashankk.com shashank chinchli

    really YQL rocks !!
    i am planning to roll out chrome extensions based on YQL
    thanks a lot for this great post;)

  • grayHat

    A REALLY nifty JavaScript library for this is flyJSONP. Almost couldn’t code without it…

    Thanks for the tutorial man!

    Cheers!