Using the Duolingo API with PHP to Get Profile Data

For those who are interested in learning a new language, Duolingo is a great place to start. It’s free, and some recent studies suggest that it’s more effective than Rosetta Stone (which is not free).

I’ve been using Duolingo for the past few months and decided to do something similar with my Duolingo profile as I did with my Code School profile – put it on the sidebar of this blog.

However, I soon discovered that I could not do that, as Duolingo’s terms of service banned Web scraping. Fortunately, I discovered that an API is available!

Using this API, I was able to write a PHP script that I host which will pull a user’s data, then filter out only language information that is pertinent (to this particular task).

Source for duolingo.php:


    function file_get_contents_curl($url){

       $ch = curl_init();
       curl_setopt($ch, CURLOPT_URL, $url);
       curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       $data = curl_exec($ch);
       return $data;

    /* gets username from querystring */
    $username = $_GET['nick'];

    /* builds profile URL on Duolingo */
    $profile_url =  '' . $username;

    /* get JSON from Duolingo API */
    $json = file_get_contents_curl($profile_url);  

    /* decode JSON into associative array */
    $results = json_decode($json,true);

    /* get nested array "languages" */
    $languages = $results['languages'];

    /* create inner div */
    $html = '<div id="duolingo_inner">';

    /* add anchor tag to user's profile */
    $html = $html . '<a href="' . $username . '" target="_blank">';

    /* add Duolingo logo from Internet */
    $html = $html . '<img src="" alt="' . $username . '\'s Duolingo profile" />';

    /* loop through languages to get only active ones */
    foreach ($languages as $language){
    	$temp_html = "
    	$include = 0;
    	foreach($language as $attribute=>$value){
    		if ($attribute == 'points' && $value > 0) {
    			$include = 1;
    		if ($attribute == 'language_string') {
    			$temp_html = $temp_html . "<tr><th colspan='2'><h2>$value</h2></th></tr>\n";
    		if ($attribute == 'points') {
    			$temp_html = $temp_html . "<tr><td class='tdleft'>Points: </td><td class='tdright'>$value</td></tr>\n";
    		if ($attribute == 'level') {
    			$temp_html = $temp_html . "<tr><td class='tdleft'>Level: </td><td class='tdright'>$value</td></tr>\n";
    		if ($attribute == 'to_next_level') {
    			$temp_html = $temp_html . "<tr><td class='tdleft'>Points to Next Level: </td><td class='tdright'>$value</td></tr>\n";
    		//echo $attribute . ' ' . $value . "
    	if ($include == 1) {
    		$temp_html = $temp_html . "</table>\n";
    		$html = $html . $temp_html;

    /* close anchor tag and inner div */
    $html = $html . "</a></div>";
    /* return the html */
    echo $html;

    /* uncommenting below will show full contents of JSON from languages section */
    //$languages_json = json_encode($languages);
    //echo $languages_json;

If you want to put this on WordPress, create a Text widget and insert the following code. This assumes that you are hosting duolingo.php in the root directory. Also, change the username in the querystring as appropriate.

<style scoped="">
#duolingo_inner {
   border: 1px solid white;
   text-align: center;
   vertical-align: middle;
   margin-left: auto;
   margin-right: auto;
   margin-bottom: 10px;
.tdleft {
 text-align: left;
.tdright {
 text-align: right;
#duolingo_inner table {
   margin-left: auto;
   margin-right: auto;
#duolingo_inner img {
   display:block !important;
   margin-left: auto;
   margin-right: auto;
   width: 50%;
<div id="duolingo_outer">
(function($) {

And that’s it! You will likely need to change the CSS if you don’t like how it looks on your browser as my widget inherits from my WP theme.

Leave a Reply