NAV Navbar
Logo
php python csharp java

Introduction

Welcome to DataForSEO API!

DataForSEO API uses REST technology for interchanging data between your application and our service. The data exchange is made by the HTTP protocol. The benefit of this method is widespread occurrence of the HTTP protocol that’s why REST API can be used almost for all programming languages.

You can create REST class by yourself or find ready to use ones to use this technology. We can provide you with ready to use classes:

Language Description
PHP Simple Rest Client PHP REST Client build with cURL. Author Fabio Agostinho Boris.
Python Simple Rest Client Python REST Client. Author DataForSEO.
C# DataForSEO Client C# DataForSEO Ready Client. Author DataForSEO.

We will show PHP, Python, C# and Java examples of these classes usage.

You can download usage examples from our website:

Language Description
PHP Examples PHP examples.
Python Examples Python examples.
C# Examples C# examples.
Java Examples Java examples.
POSTMAN Examples POSTMAN examples.
POSTMAN Documenter Online POSTMAN Documenter.

All data exchange should be UTF-8 encoded.

Also, all responses of our service are returned in the JSON format by default. We also support responses in the XML format. For this, in the end of the request you should specify .xml. Also, you can compress retrieved data in the gzip format, for this you need to specify .gzip in the request.

For example,
https://api.dataforseo.com/v2/cmn_user.xml
https://api.dataforseo.com/v2/cmn_user.gzip
https://api.dataforseo.com/v2/cmn_user.xml.gzip
instead of the standard
https://api.dataforseo.com/v2/cmn_user

Authentication

To authorize, use this code:

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');

    //do something

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")

#do something
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task cmn_key_id()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };

            // do something
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void cmn_key_id_first_method_in_api() throws Exception {
        URI url = new URI("https://api.dataforseo.com/");
        HttpClient client = HttpClientBuilder.create().build();
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        //do something
    }
}

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

First of all, you should register at our service and then you will be able to use your login and password to start using our API service.

DataForSEO API uses technology Basic Authentication.

It provides you with a possibility to use our API almost for all programming languages.

Rank Tracker API

Rank Tracker API helps to find rankings of a website in the result pages of the search engines that were specified.

The data will look like:

The tasks setting is made by few clients streams. At the same time few other clients streams constantly request our service to pick completed tasks from queue.

It is the most simplified and widespread method of work with Rank Tracker API.

You also can receive results of completed tasks using task_id or we can send them by ourselves as soon as they are ready if you specify postback_url or pingback_url when setting a task.

The time of results delivery is less for those tasks which priority is high.

Setting Rank Tasks

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}


$post_array = array();

//for example, some data selection cycle for tasks
for ($i = 0; $i < 3; $i++) {

    // example #1 - the simplest one
    // you set only a website URL and a search engine URL.
    // This search engine URL string will be searched, compared to our internal parameters
    // and used as:
    // "se_id", "loc_id", "key_id" ( actual and fresh list can be found here: "se_id":
    // https://api.dataforseo.com/v2/cmn_se , "loc_id": https://api.dataforseo.com/v2/cmn_locations ) (see example #3 for details)
    // If a task was set successfully, this *_id will be returned in results: 'v2/rnk_tasks_post' so you can use it.
    // The setting of a task can fail, if you set not-existent search engine, for example.
    // Disadvantages: You cannot work with "map pack", "maps", "mobile"
    $my_unq_id = mt_rand(0,30000000); //your unique ID. We will return it with all results
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "site" => "dataforseo.com",
    "url" => "https://www.google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
    );

    // example #2 - will return results faster than #1, but is simpler than example #3
    // All parameters should be set in the text format.
    // All data will will be searched, compared to our internal parameters
    // and used as:
    // "se_id", "loc_id", "key_id" ( actual and fresh list can be found here: "se_id": https://api.dataforseo.com/v2/cmn_se ,
    // "loc_id": https://api.dataforseo.com/v2/cmn_locations )
    // If a task was set successfully, this *_id will be returned in results: 'v2/rnk_tasks_post' so you can use it.
    // The setting of a task can fail, if you set not-existent search engine, for example.
    // Disadvantages: The process of search and comparison of provided data to our internal parameters may take some time.
    $my_unq_id = mt_rand(0,30000000); //your unique ID. will be returned with all results
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "site" => "dataforseo.com",
    "se_name" => "google.co.uk",
    "se_language" => "English",
    "loc_name_canonical"=> "London,England,United Kingdom",
    "key" => mb_convert_encoding("seo data api", "UTF-8")
    );

    // example #3 - the fastest one. All parameters should be set in our internal format.
    // Actual and fresh list can be found here: "se_id": https://api.dataforseo.com/v2/cmn_se ,
    // "loc_id": https://api.dataforseo.com/v2/cmn_locations
    $my_unq_id = mt_rand(0,30000000); //your unique ID. We will return it with all results
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "site" => "dataforseo.com",
    "se_id" => 22,
    "loc_id" => 1006886,
    "key_id" => 62845222
    );

    //This example has a cycle of up to 3 elements, but in the case of large number of tasks - send up to 100 elements per POST request
    if (count($post_array) > 99) {
        try {
            // POST /v2/rnk_tasks_post/$data
            // $tasks_data must by array with key 'data'
            $task_post_result = $client->post('v2/rnk_tasks_post', array('data' => $post_array));
            print_r($task_post_result);

            //do something with post results

            $post_array = array();
        } catch (RestClientException $e) {
            echo "\n";
            print "HTTP code: {$e->getHttpCode()}\n";
            print "Error code: {$e->getCode()}\n";
            print "Message: {$e->getMessage()}\n";
            print  $e->getTraceAsString();
            echo "\n";
        }
    }
}

if (count($post_array) > 0) {
    try {
        // POST /v2/rnk_tasks_post/$data
        // $tasks_data must by array with key 'data'
        $task_post_result = $client->post('v2/rnk_tasks_post', array('data' => $post_array));
        print_r($task_post_result);

        //do something with post results

    } catch (RestClientException $e) {
        echo "\n";
        print "HTTP code: {$e->getHttpCode()}\n";
        print "Error code: {$e->getCode()}\n";
        print "Message: {$e->getMessage()}\n";
        print  $e->getTraceAsString();
        echo "\n";
    }
}

$client = null;
?>
from random import Random
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
rnd = Random()
post_data = dict()
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    site="ranksonic.com",
    url="https://www.google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    site="dataforseo.com",
    se_name="google.co.uk",
    se_language="English",
    loc_name_canonical="London,England,United Kingdom",
    key="seo data api"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    site="dataforseo.com",
    se_id=22,
    loc_id=1006886,
    key_id=1095202
)

response = client.post("/v2/rnk_tasks_post", dict(data=post_data))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task rnk_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random();
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    site = "ranksonic.com",
                    url = "https://www.google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    site = "dataforseo.com",
                    se_name = "google.co.uk",
                    se_language = "English",
                    loc_name_canonical = "London,England,United Kingdom",
                    key = "seo data api"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    site = "dataforseo.com",
                    se_id = 22,
                    loc_id = 1006886,
                    key_id = 62845222
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/rnk_tasks_post", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                {
                    var taskState = ((IEnumerable<dynamic>)result).First();
                    if (taskState.status == "error")
                        Console.WriteLine($"Error in task with post_id {taskState.post_id}. Code: {taskState.error.code} Message: {taskState.error.message}");
                    Console.WriteLine(taskState);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void rnk_tasks_post() throws URISyntaxException, JSONException, IOException {
        URI url = new URI("https://api.dataforseo.com/v2/rnk_tasks_post");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj1 = new HashMap<>();
        postObj1.put("priority", 1);
        postObj1.put("site", "ranksonic.com");
        postObj1.put("url", "https://www.google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS");
        postValues.put(rnd.nextInt(30000000), postObj1);

        Map<String, Object> postObj2 = new HashMap<>();
        postObj2.put("priority", 1);
        postObj2.put("site", "dataforseo.com");
        postObj2.put("se_name", "google.co.uk");
        postObj2.put("se_language", "English");
        postObj2.put("loc_name_canonical", "London,England,United Kingdom");
        postObj2.put("key", "seo data api");
        postValues.put(rnd.nextInt(300000), postObj2);

        Map<String, Object> postObj3 = new HashMap<>();
        postObj3.put("priority", 1);
        postObj3.put("site", "dataforseo.com");
        postObj3.put("se_id", 22);
        postObj3.put("loc_id", 1006886);
        postObj3.put("key_id", 62845222);
        postValues.put(rnd.nextInt(30000000), postObj3);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        //post.setHeader("Accept", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse taskPostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(taskPostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && !taskPostObj.getJSONObject("error").isNull("code")) {
            JSONObject error = taskPostObj.getJSONObject("error");
            Iterator<String> keys = error.keys();
            while (keys.hasNext()) {
                String key = keys.next();
                System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
            }
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = results.getJSONObject(key).get("status").toString();
                if (status.equals("error"))
                    System.out.println("Error in task with post_id " + results.getJSONObject(key).get("post_id") + ". Code: " + results.getJSONObject(key).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(key).getJSONObject("error").get("message"));
                else {
                    System.out.println(results.getJSONObject(key).toString());
                }
            }
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.6490 sec.",
    "results_count": 3,
    "results": {
        "11913258": {
            "post_id": "11913258",
            "post_key": "seo data api",
            "post_site": "dataforseo.com",
            "task_id": 380342739,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 62845222,
            "status": "ok"
        },
        "11913049": {
            "post_id": "11913049",
            "post_key": "seo data api",
            "post_site": "dataforseo.com",
            "task_id": 380342739,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 62845222,
            "status": "ok"
        },
        "20469414": {
            "post_id": "20469414",
            "post_key": "seo data api",
            "post_site": "dataforseo.com",
            "task_id": 380342741,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 62845222,
            "status": "ok"
        }
    }
}

When we were developing the mechanism of tasks setting we tried to foresee many variations for your convenience. That’s why the range of fields is wide even though some of them are optional. Because of such flexibility for tasks settings it may seem that the process is difficult, but the things are simpler than you think.

We are sure that you will be able to pick the way of task setting that fits you the most.

All POST data should be sent in the JSON format (UTF-8 encoding). The task setting is done using POST method when array of tasks is sent in data field. We recommend to set up to 100 tasks at a time. Such limit was set because of the variations of tasks settings that you will use. If you use the field url then the processing of each task will take more time. If you use our identifiers (se_id, loc_id, key_id) then the processing of tasks will be made faster and you can set more than 100 elements at a time.

Description of the fields for a task setting:

Name of a field Type Description
priority integer execution priority
optional field
can have such values:
1 - normal execution priority (set by default)
2 - high execution priority
site string a website domain which rankings should be searched for in the SERP
required field
you can use wildcard (‘*’) to specify the search mask in the SERP. But if you decide to use a wildcard and want to include subdomains to the search then you should also specify it using wildcard.
examples:
   “example.com” (standard search)
   “example.com/” (search of exact URL)
   “example.com/eng/*” (search example.com and URLs which start with ‘/eng/’ in the SERP, such as ‘example.com/eng/index.html’ and ‘example.com/eng/help/’ etc)
   “*.example.com/eng/*” (search example.com and all its subdomain with URLs which start with ‘/eng/’ in the SERP such as ‘m.example.com/eng/index.html’ and ‘m.example.com/eng/some_url/’ etc.)
url string direct URL of a search query
optional field
you can specify a direct URL and we will sort it out to the necessary fields. Such method is the most difficult for our API processing and you should exactly specify language and location in the URL. We don’t recommend to use this method.
example:
https://www.google.co.uk/search?q=%20rank%20tracker%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS
se_id integer search engine id
optional field, if you specify se_name
you must choose one of the fields se_id or se_name
the list of available search engines with their se_id you can get by separate request List of Search Engines
also, when the information about set task is returned you will get se_id
se_name string search engine domain
optional field if you specify se_id
you must choose one of the fields se_id or se_name
the list of available search engines with se_name you can get by separate request List of Search Engines
example: “google.co.uk”
se_language string search engine language
required field if se_id is not specified
the list of available search engines with their se_language you can get by separate request List of Search Engines
example: “English”
loc_id integer search engine location id
optional field if you specify loc_name_canonical
you must choose one of the fields loc_id or loc_name_canonical
the list of available locations of search engines with their loc_id you can receive by separate request List of Locations
when the information about set task is returned you will get loc_id
please notice that we use Google Geographical Targeting including such types of locations as Country State Region Municipality City, that’s why you can specify in the field loc_id appropriate Criteria ID
loc_name_canonical string full name of search engine location
optional field if you specify loc_id
you must choose one of the fields loc_id or loc_name_canonical
the list of available locations of search engines with their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting including such types of locations as Country State Region Municipality City, that’s why you can specify in the field loc_name_canonical approriate to Canonical Name
example: “London,England,United Kingdom”
key_id integer keyword id
optional field if you specify key
when you set a task for the first time you won’t be able to know this field. But if you plan to collect rankings for this keyword we recommend you to save key_id returned after the task was set and use this field in the future.
key string keyword
optional field if you specify key_id
UTF-8 encoding
all %## will be decoded (plus symbol ‘+’ will be decoded to a space character)
if you need to use the “%” symbol for your key, please specify it as “%25”.

if this field contains ‘allinanchor:’, ‘allintext:’, ‘allintitle:’, ‘allinurl:’, ‘cache:’, ‘define:’, ‘definition:’, ‘filetype:’, ‘id:’, ‘inanchor:’, ‘info:’, ‘intext:’, ‘intitle:’, ‘inurl:’, ‘link:’, ‘related:’, ‘site:’ then the charge per task will be multiplied by 10.
se_param_add string additional parameters of search query
optional field
for example, if you want to disable auto correction of misspelling in the search query for google, you can specify “&nfpr=1”
postback_url string return URL for sending task results
optional field
if you specify this URL there will be no need to pick up tasks using Get Rank Tasks Results. We will send a result of a completed task by POST request for URL as soon as a task is completed.
pingback_url string notification URL of a completed task
optional field
when a task is completed we will notify you by GET request sent to the URL you have specified
you can use string ‘$task_id’ as $task_id variable and ‘$post_id’ as $post_id variable. we will set necessary values before sending of a request. for example:
  http://your-server.com/pingscript?taskId=$task_id
  http://your-server.com/pingscript?taskId=$task_id&postId=$post_id

When setting tasks, you send tasks data in the array using data field. The index of the task in this array ($my_unq_id variable in examples) can be used at any time after that as the post_id field. It will be returned to you with all server responses as well as our unique task_id field. Thanks to such feature, you can use this field to associate the set tasks with identifiers at your system.

Here are some examples:

  1. There is an identifier at your system of a task that you set to collect data, let it be 100500. When you set the task you send it in the data array with 100500 index like here: "{"data":{"100500":{"priority":1,"site":"ranksonic.com","se_name":"google.co.uk","se_language":"English","loc_name_canonical":"London,England,United Kingdom","key":"online rank tracker"}}}"
    When you get a result of this task, 100500 will be returned in the post_id field, and you will be able to associate the received result with the task specified at your system.
  2. You want to associate other kinds of data at your system. For instance:
    • a keyword has id=1238 at your system,
    • a search engine id=43289,
    • a location id=97435,
    • a language id=2,
    • a user for whom you want to complete this task has id=9999.

    Since the index of a task in the data array can be specified as a string, you can create this index using any symbol as a delimiter that fits you most to send the information mentioned above as a post_id. For instance, let’s see how it will look like if we use # as a delimiter. The index that includes all necessary data will have this value 1238#43289#97435#2#9999. As a result, the request for setting of a task will look like this: "{"data":{"1238#43289#97435#2#9999":{"priority":1,"site":"ranksonic.com","se_name":"google.co.uk","se_language":"English","loc_name_canonical":"London,England,United Kingdom","key":"online rank tracker"}}}"
    When you get the result of this task, you will be able to put in order the string to get the values you need. It will make the integration with our service easier for you.

As a response of API server you will receive JSON array in the field results of which there will be an information appropriate to the set tasks.

Description of the fields in the results array:

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count string number of elements in the array of results results
results array results array of tasks setting
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.
            status string results of this task setting
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
            error array informational array of error
only if status=“error”
the list of possible errors can be found below.
                  code integer error code
                  message string text description of an error
            post_id string index in the array received in a POST request
            post_site string site received in a POST request
            post_key string key received in a POST request
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            se_id integer search engine id
if status=“ok”, then this field will be always filled
You can use it for finding relations between your and our search engines.
            loc_id integer search engine location id
if status=“ok”, then this field will always be filled
You can use it for finding relations between your and our search engines.
            key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id

Possible errors codes

Error Code Meaning
404 “not found or not enough data: site” - you didn’t specify a website in the task
404 “not found or not enough data: search engine” - you’ve specified nonexistent se_id or a search engine wasn’t found by specified se_name
404 “not found or not enough data: location” - you’ve specified nonexistent loc_id or a location of a search engine wasn’t found by specified loc_name_canonical
404 “not enough data: keyword” - you didn’t specify a keyword in the task
501 “invalid ‘data’ field” - probably you haven’t passed data for the tasks in the field data. POST data should be represented as an array and added to the field data: array(‘data’ => $post_array_for_tasks)
501 “invalid data” - Data in the field data isn’t an array with the required structure.
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get Rank Tasks Results

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

/*
#1 - get ALL ready results
recommended use of getting results:
run this script by cron with 10-60 streams, every minute with random delay 0-30 sec.
usleep(mt_rand(0,30000000));
*/
try {
    //GET /v2/rnk_tasks_get
    $task_get_result = $client->get('v2/rnk_tasks_get');
    print_r($task_get_result);

    //do something with results

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}


/*
#2 - get one result by task_id
*/
try {

    // GET /api/v1/tasks_get/$task_id
    $task_get_result = $client->get('v2/rnk_tasks_get/123456789');
    print_r($task_get_result);

    //do something with result

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
response = client.get("/v2/rnk_tasks_get")
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task rnk_tasks_get()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = {Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password")))}
            };

            var response = await httpClient.GetAsync("v2/rnk_tasks_get");
            var obj = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else if (obj.results_count != 0)
            {
                foreach (var result in obj.results)
                {
                    var resultItem = ((IEnumerable<dynamic>) result).First();
                    Console.WriteLine(resultItem);
                }
            }
            else
                Console.WriteLine("no results");

            var taskid = 123456789;
            response = await httpClient.GetAsync($"v2/rnk_tasks_get/{taskid}");
            obj = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else if (obj.results_count != 0)
            {
                foreach (var result in obj.results)
                {
                    var resultItem = ((IEnumerable<dynamic>)result).First();
                    Console.WriteLine(resultItem);
                }
            }
            else
                Console.WriteLine("no results");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void rnk_task_get() throws JSONException, URISyntaxException, IOException {
        URI url = new URI("https://api.dataforseo.com/v2/rnk_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse taskGetResponse = client.execute(get);
        JSONObject taskGetObj = new JSONObject(EntityUtils.toString(taskGetResponse.getEntity()));

        if (taskGetObj.get("status") == "error") {
            JSONObject errorObj = taskGetObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!taskGetObj.get("results_count").equals(0)) {
            JSONObject results = taskGetObj.getJSONObject("results");
            JSONArray organicResults = results.getJSONArray("organic");
            System.out.println("organic:");
            for (int i = 0; i < organicResults.length(); i++) {
                System.out.println(organicResults.getJSONObject(i).get("task_id"));
                System.out.println(organicResults.getJSONObject(i));
            }
            JSONArray paidResults = results.getJSONArray("paid");
            if (paidResults.length() != 0) {
                System.out.println("paid:");
                for (int i = 0; i < paidResults.length(); i++) {
                    System.out.println(paidResults.getJSONObject(i));
                }
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0549 sec.",
    "results_count": 3,
    "results": {
        "organic": [
            {
                "post_id": "11913258",
                "task_id": 380342739,
                "se_id": 22,
                "loc_id": 1006886,
                "key_id": 62845222,
                "post_key": "seo data api",
                "post_site": "dataforseo.com",
                "result_datetime": "2018-03-13 16:18:12 +02:00",
                "result_position": 3,
                "result_url": "https://dataforseo.com/",
                "result_title": "SEO software API ⓴⓲. API for agencies. Best SEO data API provider.",
                "result_snippet_extra": "",
                "result_snippet": "DataForSEO ➤➤➤ SEO Software API ➤➤➤ SEO API data Provider built for SEO-Software companies and agencies. ✓✓✓ Great Speed, Clear Stats, Simple Pricing. Try for free now!",
                "results_count": 11500000,
                "result_extra": "",
                "result_spell": "",
                "result_se_check_url": "https://google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            },
            {
                "post_id": "11913049",
                "task_id": 380342739,
                "se_id": 22,
                "loc_id": 1006886,
                "key_id": 62845222,
                "post_key": "seo data api",
                "post_site": "dataforseo.com",
                "result_datetime": "2018-03-13 16:18:12 +02:00",
                "result_position": 3,
                "result_url": "https://dataforseo.com/",
                "result_title": "SEO software API ⓴⓲. API for agencies. Best SEO data API provider.",
                "result_snippet_extra": "",
                "result_snippet": "DataForSEO ➤➤➤ SEO Software API ➤➤➤ SEO API data Provider built for SEO-Software companies and agencies. ✓✓✓ Great Speed, Clear Stats, Simple Pricing. Try for free now!",
                "results_count": 11500000,
                "result_extra": "",
                "result_spell": "",
                "result_se_check_url": "https://google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            },
            {
                "post_id": "20469414",
                "task_id": 380342739,
                "se_id": 22,
                "loc_id": 1006886,
                "key_id": 62845222,
                "post_key": "seo data api",
                "post_site": "dataforseo.com",
                "result_datetime": "2018-03-13 16:18:12 +02:00",
                "result_position": 3,
                "result_url": "https://dataforseo.com/",
                "result_title": "SEO software API ⓴⓲. API for agencies. Best SEO data API provider.",
                "result_snippet_extra": "",
                "result_snippet": "DataForSEO ➤➤➤ SEO Software API ➤➤➤ SEO API data Provider built for SEO-Software companies and agencies. ✓✓✓ Great Speed, Clear Stats, Simple Pricing. Try for free now!",
                "results_count": 11500000,
                "result_extra": "",
                "result_spell": "",
                "result_se_check_url": "https://google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            }
        ],
        "paid": [
        ]
    }
}

You can receive results in three different ways:

  1. GET https://api.dataforseo.com/v2/rnk_tasks_get
    you will receive all complete results that have not been picked up.
  2. GET https://api.dataforseo.com/v2/rnk_tasks_get/$task_id
    after you’ve set a task there will be unique identifier returned to you in the response of our service. It is specified in the field task_id. You will be able to use it within 30 days to pick the results of the task.
  3. When setting a task (Setting Rank Tasks) you’ve specified pingback_url or postback_url. As soon as the task is completed we will send GET request to the URL you’ve specified as pingback_url or POST request with its results to the URL you specified as postback_url when the task was set.

Description of the fields for a request setting:

Name of a field Type Description
task_id string unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.

You will receive array from the API server in the field results where you will find rank tracker results.

Description of the fields in the results array:

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count string number of elements in the array of results results
results array results array of tasks
      organic array results array of organic SERP
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.
            post_id string index in the array received in a POST array
            post_site string site received in a POST array
            post_key string keyreceived in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            se_id integer search engine id
You can use it for finding relations between your and our search engines.
            loc_id integer search engine location id
You can use it for finding relations between your and our search engines.
            key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id
            result_position integer position in the SERP
            result_datetime string date and time when a result was received
in the format “year-month-date:minutes:GMT_difference_hours:GMT_difference_minutes”
for example: “2016-12-13 15:30:34 +02:00”
time zone specified at your profile settings is used
            result_url string relevant URL in the SERP
            result_title string snippet header in the SERP
            result_snippet_extra string additional snippet in the SERP
ratings, price, author, etc
            result_snippet string snippet in the SERP
            results_count integer total number of results in the SERP
            result_extra string additional elements in the SERP
you can see such items separated by commas: app, blog, books, carousel, definition_block, discussions, images, knowledge_graph, maps, news, patents, places, recipes, shopping, videos
            result_spell string auto correction of a search engine
if a search engine provided results for a keyword that was corrected, we will specify the keyword corrected by a search engine
            result_se_check_url string direct URL to search engine results
You can use it to make sure that we provide exact results
      paid array results array of paid SERP
It will be available in the future, for now all the data in this field will always have empty array.
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.
            post_id string index in the array received in a POST array
            post_site string site received in a POST array
            post_key string keyreceived in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            se_id integer search engine id
You can use it for finding relations between your and our search engines.
            loc_id integer search engine location id
You can use it for finding relations between your and our search engines.
            key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id
            result_position integer position in the SERP
            result_datetime string date and time when a result was received
in the format “year-month-date:minutes:GMT_difference_hours:GMT_difference_minutes”
for example: “2016-12-13 15:30:34 +02:00”
time zone specified at your profile settings is used
            result_url string relevant URL in the SERP
            result_title string snippet header in the SERP
            result_snippet_extra string additional snippet in the SERP
ratings, price, author, etc
            result_snippet string snippet in the SERP
            results_count integer total number of results in the SERP
            result_extra string additional elements in the SERP
you can see such items separated by commas: app, blog, books, carousel, definition_block, discussions, images, knowledge_graph, maps, news, patents, places, recipes, shopping, videos
            result_spell string auto correction of a search engine
if a search engine provided results for a keyword that was corrected, we will specify the keyword corrected by a search engine
            result_se_check_url string direct URL to search engine results
You can use it to make sure that we provide exact results

SERP API

SERP API provides you with a possibility to receive SERP (Top 100) results of specified search engines according to a certain keyword. Also, in the SERP html section you can find out how to get html page of the SERP based on a specified search engine.

The operating principle of SERP API is similar to Rank Tracker API. The main difference is that you don’t receive all complete results at once - you receive a list of task_id which results are complete, after you can receive each result separately. This is due to the fact that each of tasks has huge data amount.

The time of results delivery is less for those tasks which priority is high.

Setting SERP Tasks

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}


$post_array = array();

//for example, some data selection cycle for tasks
for ($i = 0; $i < 3; $i++) {

    // example #1 - simplest
    // you set only a website URL and a search engine URL.
    // This search engine URL string will be searched, compared to our internal parameters
    // and used as:
    // "se_id", "loc_id", "key_id" ( actual and fresh list can be found here: "se_id":
    // https://api.dataforseo.com/v2/cmn_se , "loc_id": https://api.dataforseo.com/v2/cmn_locations ) (see example #3 for details)
    // If a task was set successfully, this *_id will be returned in results: 'v2/srp_tasks_post' so you can use it.
    // The setting of a task can fail, if you set not-existent search engine, for example.
    // Disadvantages: You cannot work with "map pack", "maps", "mobile"
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "url" => "https://www.google.co.uk/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
    );

    // example #2 - will return results faster than #1, but is simpler than example #3
    // All parameters should be set in the text format.
    // All data will be will be searched, compared to our internal parameters
    // and used as:
    // "se_id", "loc_id", "key_id" ( actual and
    // fresh list can be found here: "se_id": https://api.dataforseo.com/v2/cmn_se ,
    // "loc_id": https://api.dataforseo.com/v2/cmn_locations )
    // If a task was set successfully, this *_id will be returned in results: 'v2/srp_tasks_post' so you can use it.
    // The setting of a task can fail, if you set not-existent search engine, for example.
    // Disadvantages: The process of search and comparison of provided data to our internal parameters may take some time.
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "se_name" => "google.co.uk",
    "se_language" => "English",
    "loc_name_canonical"=> "London,England,United Kingdom",
    "key" =>  mb_convert_encoding("online rank checker", "UTF-8")
    );

    // example #3 - the fastest one. All parameters should be set in our internal format.
    // Actual and fresh list can be found here: "se_id": https://api.dataforseo.com/v2/cmn_se ,
    // "loc_id": https://api.dataforseo.com/v2/cmn_locations
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "se_id" => 22,
    "loc_id" => 1006886,
    "key_id" => 1095202
    );

    //This example has a cycle of up to 3 elements, but in the case of large number of tasks - send up to 100 elements per POST request
    if (count($post_array) > 99) {
        try {
            // POST /v2/srp_tasks_post/$data
            // $tasks_data must by array with key 'data'
            $task_post_result = $client->post('v2/srp_tasks_post', array('data' => $post_array));
            print_r($task_post_result);

            //do something with post results

            $post_array = array();
        } catch (RestClientException $e) {
            echo "\n";
            print "HTTP code: {$e->getHttpCode()}\n";
            print "Error code: {$e->getCode()}\n";
            print "Message: {$e->getMessage()}\n";
            print  $e->getTraceAsString();
            echo "\n";
        }
    }
}

if (count($post_array) > 0) {
    try {
        // POST /v2/srp_tasks_post/$data
        // $tasks_data must by array with key 'data'
        $task_post_result = $client->post('v2/srp_tasks_post', array('data' => $post_array));
        print_r($task_post_result);

        //do something with post results

    } catch (RestClientException $e) {
        echo "\n";
        print "HTTP code: {$e->getHttpCode()}\n";
        print "Error code: {$e->getCode()}\n";
        print "Message: {$e->getMessage()}\n";
        print  $e->getTraceAsString();
        echo "\n";
    }
}

$client = null;
?>
from random import Random
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
rnd = Random() #you can set as "index of post_data" your ID, string, etc. we will return it with all results.
post_data = dict()
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    url="https://www.google.co.uk/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_name="google.co.uk",
    se_language="English",
    loc_name_canonical="London,England,United Kingdom",
    key="online rank checker"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_id=22,
    loc_id=1006886,
    key_id=1095202
)

response = client.post("/v2/srp_tasks_post", dict(data=post_data))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task srp_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    url = "https://www.google.co.uk/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_name = "google.co.uk",
                    se_language = "English",
                    loc_name_canonical = "London,England,United Kingdom",
                    key = "online rank checker"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_id = 22,
                    loc_id = 1006886,
                    key_id = 1095202
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/srp_tasks_post", new StringContent(JsonConvert.SerializeObject(new {data = postObject})));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                {
                    var taskState = ((IEnumerable<dynamic>) result).First();
                    if (taskState.status == "error")
                        Console.WriteLine($"Error in task with post_id {taskState.post_id}. Code: {taskState.error.code} Message: {taskState.error.message}");
                    Console.WriteLine(taskState);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void srp_tasks_post() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_tasks_post");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj1 = new HashMap<>();
        postObj1.put("priority", 1);
        postObj1.put("url", "https://www.google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS");
        postValues.put(rnd.nextInt(30000000), postObj1);

        Map<String, Object> postObj2 = new HashMap<>();
        postObj2.put("priority", 1);
        postObj2.put("se_name", "google.co.uk");
        postObj2.put("se_language", "English");
        postObj2.put("loc_name_canonical", "London,England,United Kingdom");
        postObj2.put("key", "online rank checker");
        postValues.put(rnd.nextInt(300000), postObj2);

        Map<String, Object> postObj3 = new HashMap<>();
        postObj3.put("priority", 1);
        postObj3.put("se_id", 22);
        postObj3.put("loc_id", 1006886);
        postObj3.put("key_id", 1095202);
        postValues.put(rnd.nextInt(30000000), postObj3);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse taskPostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(taskPostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = results.getJSONObject(key).get("status").toString();
                if (status.equals("error"))
                    System.out.println("Error in task with post_id " + results.getJSONObject(key).get("post_id") + ". Code: " + results.getJSONObject(key).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(key).getJSONObject("error").get("message"));
                else {
                    System.out.println(results.getJSONObject(key).toString());
                }
            }
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.6490 sec.",
    "results_count": 9,
    "results": {
        "11913049": {
            "post_id": 11913049,
            "post_key": "online rank checker",
            "task_id": 404227822,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        },
        "20469414": {
            "post_id": 20469414,
            "post_key": "online rank checker",
            "task_id": 404227823,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        },
        "6273173": {
            "post_id": 6273173,
            "post_key": "online rank checker",
            "task_id": 404227824,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        },
        "27408598": {
            "post_id": 27408598,
            "post_key": "online rank checker",
            "task_id": 404227825,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        },
        "19840083": {
            "post_id": 19840083,
            "post_key": "online rank checker",
            "task_id": 404227826,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        },
        "6054604": {
            "post_id": 6054604,
            "post_key": "online rank checker",
            "task_id": 404227827,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        },
        "8626195": {
            "post_id": 8626195,
            "post_key": "",
            "task_id": 404227828,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        },
        "18786140": {
            "post_id": 18786140,
            "post_key": "online rank checker",
            "task_id": 404227829,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        },
        "13056693": {
            "post_id": 13056693,
            "post_key": "online rank checker",
            "task_id": 404227830,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "status": "ok"
        }
    }
}

All POST data should be sent in the JSON format (UTF-8 encoding). Task setting is made by the POST method, passing array of tasks in data field. We recommend to set up to 100 tasks at a time. Such limit was set because of the variations of tasks settings that you will use. If you use the field url then the processing of each task will take more time. If you use our identifiers (se_id, loc_id, key_id), then the processing of tasks will be made faster and you can set more than 100 elements at a time.

You also can receive results of completed tasks using task_id or we can send them by ourselves as soon as they are ready if you specify postback_url or pingback_url when setting a task.

Description of the fields for a task setting:

Name of a field Type Description
priority integer execution priority
optional field
can have such values:
1 - normal execution priority (set by default)
2 - high execution priority
url string direct URL of a search query
optional field
you can specify a direct URL and we will sort it out to the necessary fields. Such method is the most difficult for our API processing and you should exactly specify language and location in the URL. We don’t recommend to use this method.
example:
https://www.google.co.uk/search?q=%20rank%20tracker%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS
se_id integer search engine id
optional field, if you specify se_name
you must choose one of the fields se_id or se_name
the list of available search engines with se_id you can get by separate request List of Search Engines
also, when the information about set task is returned you will get se_id
se_name string search engine domain
optional field if you specify se_id
you must choose one of the fields se_id or se_name
the list of available search engines with se_name you can get by separate request List of Search Engines
example: “google.co.uk”
se_language string search engine language
required field if se_id is not specified
the list of available search engines with se_language you can get by separate request List of Search Engines
example: “English”
loc_id integer search engine location id
optional field if you specify loc_name_canonical
you must choose one of the fields loc_id or loc_name_canonical
the list of available locations of search engines with loc_id you can get by separate request List of Locations
also when the information about set task is returned you will get loc_id
please notice that we use Google Geographical Targeting including such types of locations as Country State Region Municipality City, that’s why you can specify loc_id appropriate Criteria ID
loc_name_canonical string full name of search engine location
optional field if you specify loc_id
you must choose one of the fields loc_id or loc_name_canonical
the list of available locations of search engines with loc_name_canonical you can get by separate List of Locations
please notice that we use Google Geographical Targeting including such types of locations as Country State Region Municipality City, that’s why you can specify loc_name_canonical appropriate Canonical Name
example: “London,England,United Kingdom”
key_id integer keyword id
optional field if you specify key
when you set a task for the first time you won’t be able to know this field. But if you plan to collect rankings for this keyword we recommend you to save key_id returned after the task was set and use this field in the future.
key string keyword
optional field if you specify key_id
UTF-8 encoding
all %## will be decoded (plus symbol ‘+’ will be decoded to a space character)
if you need to use the “%” symbol for your key, please specify it as “%25”

if this field contains ‘allinanchor:’, ‘allintext:’, ‘allintitle:’, ‘allinurl:’, ‘cache:’, ‘define:’, ‘definition:’, ‘filetype:’, ‘id:’, ‘inanchor:’, ‘info:’, ‘intext:’, ‘intitle:’, ‘inurl:’, ‘link:’, ‘related:’, ‘site:’ then the charge per task will be multiplied by 10.
se_param_add string additional parameters of search query
optional field
for instance, if you want to disable auto correction of misspelling in the search query for google, you can specify “&nfpr=1”
postback_url string return URL for sending task results
optional field
if you specify this URL there will be no need to pick up tasks using Get SERP Tasks Results. We will send a result of a completed task by POST request for URL as soon as a task is completed.
pingback_url string notification URL of a completed task
optional field
when a task is completed we will notify you by GET request sent to the URL you have specified
you can use string ‘$task_id’ as $task_id variable and ‘$post_id’ as $post_id variable. we will set necessary values before sending of a request. for example:
  http://your-server.com/pingscript?taskId=$task_id
  http://your-server.com/pingscript?taskId=$task_id&postId=$post_id

When setting tasks, you send tasks data in the array using data field. The index of the task in this array ($my_unq_id variable in examples) can be used at any time after that as the post_id field. It will be returned to you with all server responses as well as our unique task_id field. Thanks to such feature, you can use this field to associate the set tasks with identifiers at your system.

Here are some examples:

  1. There is an identifier at your system of a task that you set to collect data, let it be 100500. When you set the task you send it in the data array with 100500 index like here: "{"data":{"100500":{"priority":1,"se_name":"google.co.uk","se_language":"English","loc_name_canonical":"London,England,United Kingdom","key":"online rank tracker"}}}"
    When you get a result of this task, 100500 will be returned in the post_id field, and you will be able to associate the received result with the task specified at your system.
  2. You want to associate other kinds of data at your system. For instance:
    • a keyword has id=1238 at your system,
    • a search engine id=43289,
    • a location id=97435,
    • a language id=2,
    • a user for whom you want to complete this task has id=9999.

    Since the index of a task in the data array can be specified as a string, you can create this index using any symbol as a delimiter that fits you most to send the information mentioned above as a post_id. For instance, let’s see how it will look like if we use # as a delimiter. The index that includes all necessary data will have this value 1238#43289#97435#2#9999. As a result, the request for setting of a task will look like this: "{"data":{"1238#43289#97435#2#9999":{"priority":1,"se_name":"google.co.uk","se_language":"English","loc_name_canonical":"London,England,United Kingdom","key":"online rank tracker"}}}"
    When you get the result of this task, you will be able to put in order the string to get the values you need. It will make the integration with our service easier for you.

As a response of API server you will receive JSON array in the field results of which there will be an information appropriate to the set tasks.

Description of the fields in the results array:

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of error
results_time string execution time, seconds
results_count string number of elements in the array of results results
results array results array of tasks setting
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.
            status string results of this task setting
“ok” - success
“error” - error
if status=“error”, then you can see more detailed information of array error error
            error array informational array of error
only if status=“error”
the list of possible errors can be found below.
                  code integer error code
                  message string text description of error
            post_id string index in the array received in a POST request
            post_key string key received in a POST request
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            se_id integer search engine id
if status=“ok”, then this field will be always filled
You can use it for finding relations between your and our search engines.
            loc_id integer search engine location id
if status=“ok”, then this field will be always filled
You can use it for finding relations between your and our search engines.
            key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id

Possible errors codes

Error Code Meaning
404 “not found or not enough data: site” - you didn’t specify a website in the task
404 “not found or not enough data: search engine” - you’ve specified nonexistent se_id or a search engine wasn’t found by specified se_name
404 “not found or not enough data: location” - you’ve specified nonexistent loc_id or a location of a search engine wasn’t found by specified loc_name_canonical
404 “not enough data: keyword” - you didn’t specify a keyword in the task
501 “invalid ‘data’ field” - probably you haven’t passed data for the tasks in the fielddata. POST data should be represented as an array and added to the field data: array(‘data’ => $post_array_for_tasks)
501 “invalid data” - data in the field data isn’t an array with the required structure.
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get SERP Completed Tasks

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/srp_tasks_get
    $tasks_get_result = $client->get('v2/srp_tasks_get');
    print_r($tasks_get_result);

    //get tasks one by one

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
response = client.get("/v2/srp_tasks_get")
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task srp_tasks_get()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/srp_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    Console.WriteLine(completedTask);
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void srp_tasks_get() throws JSONException, URISyntaxException, IOException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse taskGetResponse = client.execute(get);
        JSONObject taskGetObj = new JSONObject(EntityUtils.toString(taskGetResponse.getEntity()));

        if (taskGetObj.get("status") == "error") {
            JSONObject errorObj = taskGetObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!taskGetObj.get("results_count").equals(0)) {
            JSONArray results = taskGetObj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.getJSONObject(i));
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0120 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 107,
            "post_id": 11577837,
            "post_key": "online rank checker",
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202,
            "results_count": 4690000,
            "result_extra": "videos",
            "result_spell": "",
            "result_se_check_url": "https:\/\/google.co.uk\/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
        }
    ]
}

You will get the list of complete results, that you haven’t collected yet. After you collect a result the task will be removed from this list.

If you specify pingback_url or postback_url you can skip usage of srp_tasks_get to get the list of completed tasks. Our system send you GET request to the pingback_url or send POST request with results to the postback_url.

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Description of the fields in the results array:

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count string number of elements in the array of results results
results array results array of tasks
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time
            post_id string index in the array received in a POST array
            post_key string key received in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            se_id integer search engine id
You can use it for finding relations between your and our search engines
            loc_id integer search engine location id
You can use it for finding relations between your and our search engines.
            key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id
            results_count integer total number of results in the SERP
            result_extra string additional elements in the SERP
you can see such items separated by commas: app, blog, books, carousel, featured_snippet, discussions, images, knowledge_graph, maps, news, patents, places, recipes, shopping, videos
            result_spell string auto correction of a search engine
if a search engine provided results for a keyword that was corrected, we will specify the keyword corrected by a search engine
            result_se_check_url string direct URL to search engine results
You can use it to make sure that we provide exact results

Get SERP Results by task_id

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/srp_tasks_get
    $tasks_get_result = $client->get('v2/srp_tasks_get');
    print_r($tasks_get_result);
    if ($tasks_get_result["status"] == "ok") {
        foreach($tasks_get_result["results"] as $tasks_get_row) {
            // #2 - get result by task_id
            //GET /v2/srp_tasks_get/$task_id
            $serp_result = $client->get('v2/srp_tasks_get/'.$tasks_get_row["task_id"]);
            print_r($serp_result);

            //do something with results
        }
    }
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
completed_tasks_response = client.get("/v2/srp_tasks_get")
if completed_tasks_response["status"] == "error":
    print("error. Code: %d Message: %s" % (completed_tasks_response["error"]["code"], completed_tasks_response["error"]["message"]))
else:
    results = completed_tasks_response["results"]
    print(results)
    for result in results:
        srp_response = client.get("/v2/srp_tasks_get/%d" % (result["task_id"]))
        if srp_response["status"] == "error":
            print("error. Code: %d Message: %s" % (srp_response["error"]["code"], srp_response["error"]["message"]))
        else:
            print(srp_response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task srp_tasks_get_by_task_id()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/srp_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    var serpResponse = await httpClient.GetAsync($"v2/srp_tasks_get/{completedTask.task_id}");
                    var serpObj = JsonConvert.DeserializeObject<dynamic>(await serpResponse.Content.ReadAsStringAsync());
                    if (serpObj.status == "error")
                        Console.WriteLine($"error. Code: {serpObj.error.code} Message: {serpObj.error.message}");
                    foreach (var serpResult in serpObj.results)
                        Console.WriteLine(((IEnumerable<dynamic>)serpResult).First());
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void srp_tasks_get_by_task_id() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse completedTasksResponse = client.execute(get);
        JSONObject completedTasksObj = new JSONObject(EntityUtils.toString(completedTasksResponse.getEntity()));

        if (completedTasksObj.get("status") == "error") {
            JSONObject errorObj = completedTasksObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!completedTasksObj.get("results_count").equals(0)) {
            JSONArray results = completedTasksObj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                HttpGet getSerp = new HttpGet("https://api.dataforseo.com/v2/srp_tasks_get/" + results.getJSONObject(i).get("task_id"));
                System.out.println(results.getJSONObject(i).get("task_id"));
                getSerp.setHeader("Content-type", "application/json");
                getSerp.setHeader("Authorization", "Basic " + basicAuth);
                HttpResponse serpResponse = client.execute(getSerp);
                JSONObject serpObj = new JSONObject(EntityUtils.toString(serpResponse.getEntity()));
                if (serpObj.get("status").equals("error")) {
                    System.out.println("error. Code:" + serpObj.getJSONObject("error").get("code") + " Message: " + serpObj.getJSONObject("error").get("message"));
                } else {
                    System.out.println(serpObj.toString());
                }
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0135 sec.",
    "results_count": 100,
    "results": {
            "organic": [
                {
                    "post_id": 2833944,
                    "task_id": 405460981,
                    "se_id": 22,
                    "loc_id": 1006886,
                    "key_id": 1095202,
                    "post_key": "online rank checker",
                    "result_datetime": "2016-12-19 14:41:33 +02:00",
                    "result_position": 1,
                    "result_url": "https:\/\/serps.com\/tools\/rank-checker\/",
                    "result_title": "Free Keyword Rank Checker - Google & Yahoo | SERPs.com",
                    "result_snippet_extra": "",
                    "result_snippet": "International and local keyword rankings. Check keyword rankings positions in Google or Yahoo from over 100 country and language combinations.",
                    "results_count": 4690000,
                    "result_extra": "videos",
                    "result_spell": "",
                    "result_se_check_url": "https:\/\/google.co.uk\/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                },
                {
                    "post_id": 2833944,
                    "task_id": 405460981,
                    "se_id": 22,
                    "loc_id": 1006886,
                    "key_id": 1095202,
                    "post_key": "online rank checker",
                    "result_datetime": "2016-12-19 14:41:33 +02:00",
                    "result_position": 2,
                    "result_url": "https:\/\/ranksonic.com\/",
                    "result_snippet_extra": "Rating: 4.6 - ‎6,054 reviews",
                    "result_title": "RankSonic ⓴⓰ - Rank Tracking SEO software. Website ranking SEO ...",
                    "result_snippet": "⓴⓰ Rank Tracking SEO Software ? Keyword Google online search engine seo \n... Check what potential your keywords have to evaluate their competition level.",
                    "results_count": 4690000,
                    "result_extra": "videos",
                    "result_spell": "",
                    "result_se_check_url": "https:\/\/google.co.uk\/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                },


                {
                    "post_id": 2833944,
                    "task_id": 405460981,
                    "se_id": 22,
                    "loc_id": 1006886,
                    "key_id": 1095202,
                    "post_key": "online rank checker",
                    "result_datetime": "2016-12-19 14:41:33 +02:00",
                    "result_position": 99,
                    "result_url": "http:\/\/www.prcheckingtool.com\/",
                    "result_title": "PR Checking Tool - Website Ranking Checker",
                    "result_snippet_extra": "",
                    "result_snippet": "It is a simple yet powerful tool checking the online ranking of different websites. If you think that its sole utilization is for web ranking only then you are wrong as it ...",
                    "results_count": 4690000,
                    "result_extra": "videos",
                    "result_spell": "",
                    "result_se_check_url": "https:\/\/google.co.uk\/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                }
        ],


        "paid": [
                {
                    "post_id": 2833944,
                    "task_id": 405460981,
                    "se_id": 22,
                    "loc_id": 1006886,
                    "key_id": 1095202,
                    "post_key": "online rank checker",
                    "result_datetime": "2016-12-19 14:41:33 +02:00",
                    "result_position": 1,
                    "result_url": "https:\/\/www.seorankmonitor.com\/",
                    "result_title": "SEO Rank Monitor - The Most Complete Rank Checker",
                    "result_snippet_extra": "",
                    "result_snippet": "Everything you need to keep your Website Ranked High - Start a Free Trial Now!",
                    "results_count": 4690000,
                    "result_extra": "videos",
                    "result_spell": "",
                    "result_se_check_url": "https:\/\/google.co.uk\/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                }
        ],
        "extra": {
            "related": [
                [
                    "what is seo and how it works",
                    "seo definition",
                    "seo google",
                    "how to do seo",
                    "seo wiki",
                    "seo tutorial",
                    "seo tutorial",
                    "seo company"                    
                ]
            ]
        }
    }
}

Description of the fields for a request setting:

Name of a field Type Description
task_id string unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Description of the fields in the results array:

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count string number of elements in the array of results results
results array results array of tasks setting
      organic array results array of organic SERP
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time. You are charged for each GET request for results receiving.
            post_id string index in the array received in a POST array
            se_id integer search engine id
            loc_id integer search engine location id
You can use it for finding relations between your and our search engines.
            key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id
            post_key string keyreceived in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            result_position integer position in the SERP
            result_datetime string date and time when a result was received
in the format “year-month-date:minutes:GMT_difference_hours:GMT_difference_minutes”
for example: “2016-12-13 15:30:34 +02:00”
the time zone specified at your profile settings is used
            result_url string relevant URL in the SERP
            result_title string snippet header in the SERP
            result_snippet_extra string additional snippet in the SERP
ratings, price, author, etc
            result_snippet string snippet in the SERP
            results_count integer total number of results in the SERP
            result_extra string additional elements in the SERP
you can see such items separated by commas: app, blog, books, carousel, featured_snippet, discussions, images, knowledge_graph, maps, news, patents, places, recipes, shopping, videos
            result_spell string auto correction of a search engine
if a search engine provided results for a keyword that was corrected, we will specify the keyword corrected by a search engine
            result_se_check_url string direct URL to search engine results
You can use it to make sure that we provide exact results
      paid array results array of paid SERP
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.
            post_id string index in the array received in a POST array
            se_id integer search engine id
            loc_id integer search engine location id
You can use it for finding relations between your and our search engines.
            key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id
            post_key string keyreceived in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            result_position integer position in the SERP
            result_datetime string date and time when a result was received
in the format “year-month-date:minutes:GMT_difference_hours:GMT_difference_minutes”
for example: “2016-12-13 15:30:34 +02:00”
the time zone specified at your profile settings is used
            result_url string relevant URL in the SERP
            result_title string snippet header in the SERP
            result_snippet_extra string additional snippet in the SERP
ratings, price, author, etc
            result_snippet string snippet in the SERP
            results_count integer total number of results in the SERP
            result_extra string additional elements in the SERP
you can see such items separated by commas: app, blog, books, carousel, featured_snippet, discussions, images, knowledge_graph, maps, news, patents, places, recipes, shopping, videos
            result_spell string auto correction of a search engine
if a search engine provided results for a keyword that was corrected, we will specify the keyword corrected by a search engine
            result_se_check_url string direct URL to search engine results
You can use it to make sure that we provide exact results
      extra array results array of extra SERP elements
extra SERP elements are available only for google search engine
            related array array of ‘related search queries’ strings
this array will be present if the element is in the SERP

Possible errors codes

Error Code Meaning
102 “task in queue” - the task is being enqueued to handling, please, try again later
201 “task handed” - the task has been received and sent to handling, please, try again later
202 “in progress” - the task is in the handling process, please, try again later
404 “search engine did not return results” - SERP is empty. Check if you have added key correctly
404 “top results not found” - there is no SERP with specified parameters

Setting SERP HTML Tasks

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}


$post_array = array();

//for example, some data selection cycle for tasks
for ($i = 0; $i < 3; $i++) {

    // example #1 - simplest
    // you set only a website URL and a search engine URL.
    // This search engine URL string will be searched, compared to our internal parameters
    // and used as:
    // "se_id", "loc_id", "key_id" ( actual and fresh list can be found here: "se_id":
    // https://api.dataforseo.com/v2/cmn_se , "loc_id": https://api.dataforseo.com/v2/cmn_locations ) (see example #3 for details)
    // If a task was set successfully, this *_id will be returned in results: 'v2/srp_html_tasks_post' so you can use it.
    // The setting of a task can fail, if you set not-existent search engine, for example.
    // Disadvantages: You cannot work with "map pack", "maps", "mobile"
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "url" => "https://www.google.co.uk/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
    );

    // example #2 - will return results faster than #1, but is simpler than example #3
    // All parameters should be set in the text format.
    // All data will be will be searched, compared to our internal parameters
    // and used as:
    // "se_id", "loc_id", "key_id" ( actual and
    // fresh list can be found here: "se_id": https://api.dataforseo.com/v2/cmn_se ,
    // "loc_id": https://api.dataforseo.com/v2/cmn_locations )
    // If a task was set successfully, this *_id will be returned in results: 'v2/srp_html_tasks_post' so you can use it.
    // The setting of a task can fail, if you set not-existent search engine, for example.
    // Disadvantages: The process of search and comparison of provided data to our internal parameters may take some time.
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "se_name" => "google.co.uk",
    "se_language" => "English",
    "loc_name_canonical"=> "London,England,United Kingdom",
    "key" =>  mb_convert_encoding("online rank checker", "UTF-8")
    );

    // example #3 - the fastest one. All parameters should be set in our internal format.
    // Actual and fresh list can be found here: "se_id": https://api.dataforseo.com/v2/cmn_se ,
    // "loc_id": https://api.dataforseo.com/v2/cmn_locations
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.
    $post_array[$my_unq_id] = array(
    "priority" => 1,
    "se_id" => 22,
    "loc_id" => 1006886,
    "key_id" => 1095202
    );

    //This example has a cycle of up to 3 elements, but in the case of large number of tasks - send up to 100 elements per POST request
    if (count($post_array) > 99) {
        try {
            // POST /v2/srp_tasks_post/$data
            // $tasks_data must by array with key 'data'
            $task_post_result = $client->post('v2/srp_html_tasks_post', array('data' => $post_array));
            print_r($task_post_result);

            //do something with post results

            $post_array = array();
        } catch (RestClientException $e) {
            echo "\n";
            print "HTTP code: {$e->getHttpCode()}\n";
            print "Error code: {$e->getCode()}\n";
            print "Message: {$e->getMessage()}\n";
            print  $e->getTraceAsString();
            echo "\n";
        }
    }
}

if (count($post_array) > 0) {
    try {
        // POST /v2/srp_tasks_post/$data
        // $tasks_data must by array with key 'data'
        $task_post_result = $client->post('v2/srp_html_tasks_post', array('data' => $post_array));
        print_r($task_post_result);

        //do something with post results

    } catch (RestClientException $e) {
        echo "\n";
        print "HTTP code: {$e->getHttpCode()}\n";
        print "Error code: {$e->getCode()}\n";
        print "Message: {$e->getMessage()}\n";
        print  $e->getTraceAsString();
        echo "\n";
    }
}

$client = null;
?>
from random import Random
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
rnd = Random() #you can set as "index of post_data" your ID, string, etc. we will return it with all results.
post_data = dict()
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    url="https://www.google.co.uk/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_name="google.co.uk",
    se_language="English",
    loc_name_canonical="London,England,United Kingdom",
    key="online rank checker"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_id=22,
    loc_id=1006886,
    key_id=1095202
)

response = client.post("/v2/srp_html_tasks_post", dict(data=post_data))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task srp_html_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    url = "https://www.google.co.uk/search?q=online%20rank%20checker&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_name = "google.co.uk",
                    se_language = "English",
                    loc_name_canonical = "London,England,United Kingdom",
                    key = "online rank checker"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_id = 22,
                    loc_id = 1006886,
                    key_id = 1095202
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/srp_html_tasks_post", new StringContent(JsonConvert.SerializeObject(new {data = postObject})));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                {
                    var taskState = ((IEnumerable<dynamic>) result).First();
                    if (taskState.status == "error")
                        Console.WriteLine($"Error in task with post_id {taskState.post_id}. Code: {taskState.error.code} Message: {taskState.error.message}");
                    Console.WriteLine(taskState);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void srp_html_tasks_post() throws IOException, JSONException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_html_tasks_post");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj1 = new HashMap<>();
        postObj1.put("priority", 1);
        postObj1.put("url", "https://www.google.co.uk/search?q=seo%20data%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS");
        postValues.put(rnd.nextInt(30000000), postObj1);

        Map<String, Object> postObj2 = new HashMap<>();
        postObj2.put("priority", 1);
        postObj2.put("se_name", "google.co.uk");
        postObj2.put("se_language", "English");
        postObj2.put("loc_name_canonical", "London,England,United Kingdom");
        postObj2.put("key", "online rank checker");
        postValues.put(rnd.nextInt(300000), postObj2);

        Map<String, Object> postObj3 = new HashMap<>();
        postObj3.put("priority", 1);
        postObj3.put("se_id", 22);
        postObj3.put("loc_id", 1006886);
        postObj3.put("key_id", 1095202);
        postValues.put(rnd.nextInt(30000000), postObj3);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse taskPostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(taskPostResponse.getEntity()));

        if (!taskPostObj.isNull("results_count") && !taskPostObj.get("results_count").equals(0)) {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = results.getJSONObject(key).get("status").toString();
                if (status.equals("error"))
                    System.out.println("Error in task with post_id " + results.getJSONObject(key).get("post_id") + ". Code: " + results.getJSONObject(key).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(key).getJSONObject("error").get("message"));
                else {
                    System.out.println(results.getJSONObject(key).toString());
                }
            }
        } else if (taskPostObj.get("status").equals("error")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.6490 sec.",
    "results_count": 3,
    "results": {
        "20469414": {
            "status": "ok",
            "post_id": 20469414,
            "post_key": "online rank checker",
            "task_id": 348906716,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202
        },
        "6273173": {
            "status": "ok",
            "post_id": 6273173,
            "post_key": "online rank checker",
            "task_id": 348908817,
            "se_id": 22,
            "loc_id": 9041110,
            "key_id": 1095202
        },
        "19840083": {
            "status": "ok",
            "post_id": 19840083,
            "post_key": "online rank checker",
            "task_id": 348909840,
            "se_id": 22,
            "loc_id": 1006886,
            "key_id": 1095202
        }
    }
}

All POST data should be sent in the JSON format (UTF-8 encoding). Task setting is made by the POST method, passing array of tasks in data field. We recommend to set up to 100 tasks at a time. Such limit was set because of the variations of tasks settings that you will use. If you use the field url then the processing of each task will take more time. If you use our identifiers (se_id, loc_id, key_id), then the processing of tasks will be made faster and you can set more than 100 elements at a time.

You also can receive results of completed tasks using task_id or we can send them by ourselves as soon as they are ready if you specify postback_url or pingback_url when setting a task.

Description of the fields for a task setting:

Name of a field Type Description
priority integer execution priority
optional field
can have such values:
1 - normal execution priority (set by default)
2 - high execution priority
url string direct URL of a search query
optional field
you can specify a direct URL and we will sort it out to the necessary fields. Such method is the most difficult for our API processing and you should exactly specify language and location in the URL. We don’t recommend to use this method.
example:
https://www.google.co.uk/search?q=%20rank%20tracker%20api&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS
se_id integer search engine id
optional field, if you specify se_name
you must choose one of the fields se_id or se_name
the list of available search engines with se_id you can get by separate request List of Search Engines
also, when the information about set task is returned you will get se_id
se_name string search engine domain
optional field if you specify se_id
you must choose one of the fields se_id or se_name
the list of available search engines with se_name you can get by separate request List of Search Engines
example: “google.co.uk”
se_language string search engine language
required field if se_id is not specified
the list of available search engines with se_language you can get by separate request List of Search Engines
example: “English”
loc_id integer search engine location id
optional field if you specify loc_name_canonical
you must choose one of the fields loc_id or loc_name_canonical
the list of available locations of search engines with loc_id you can get by separate request List of Locations
also when the information about set task is returned you will get loc_id
please notice that we use Google Geographical Targeting including such types of locations as Country State Region Municipality City, that’s why you can specify loc_id appropriate Criteria ID
loc_name_canonical string full name of search engine location
optional field if you specify loc_id
you must choose one of the fields loc_id or loc_name_canonical
the list of available locations of search engines with loc_name_canonical you can get by separate List of Locations
please notice that we use Google Geographical Targeting including such types of locations as Country State Region Municipality City, that’s why you can specify loc_name_canonical appropriate Canonical Name
example: “London,England,United Kingdom”
key_id integer keyword id
optional field if you specify key
when you set a task for the first time you won’t be able to know this field. But if you plan to collect rankings for this keyword we recommend you to save key_id returned after the task was set and use this field in the future.
key string keyword
optional field if you specify key_id
UTF-8 encoding
all %## will be decoded (plus symbol ‘+’ will be decoded to a space character)
if you need to use the “%” symbol for your key, please specify it as “%25”

if this field contains ‘allinanchor:’, ‘allintext:’, ‘allintitle:’, ‘allinurl:’, ‘cache:’, ‘define:’, ‘definition:’, ‘filetype:’, ‘id:’, ‘inanchor:’, ‘info:’, ‘intext:’, ‘intitle:’, ‘inurl:’, ‘link:’, ‘related:’, ‘site:’ then the charge per task will be multiplied by 10.
se_param_add string additional parameters of search query
optional field
for instance, if you want to disable auto correction of misspelling in the search query for google, you can specify “&nfpr=1”
postback_url string return URL for sending task results
optional field
if you specify this URL there will be no need to pick up tasks using Get SERP HTML Tasks Results. We will send a result of a completed task by POST request for URL as soon as a task is completed.
The data that is sent to you will be in ZIP archive and you will need to decode it.
pingback_url string notification URL of a completed task
optional field
when a task is completed we will notify you by GET request sent to the URL you have specified
you can use string ‘$task_id’ as $task_id variable and ‘$post_id’ as $post_id variable. we will set necessary values before sending of a request. for example:
  http://your-server.com/pingscript?taskId=$task_id
  http://your-server.com/pingscript?taskId=$task_id&postId=$post_id

When setting tasks, you send tasks data in the array using data field. The index of the task in this array ($my_unq_id variable in examples) can be used at any time after that as the post_id field. It will be returned to you with all server responses as well as our unique task_id field. Thanks to such feature, you can use this field to associate the set tasks with identifiers at your system.

Here are some examples:

  1. There is an identifier at your system of a task that you set to collect data, let it be 100500. When you set the task you send it in the data array with 100500 index like here: "{"data":{"100500":{"priority":1,"se_name":"google.co.uk","se_language":"English","loc_name_canonical":"London,England,United Kingdom","key":"online rank tracker"}}}"
    When you get a result of this task, 100500 will be returned in the post_id field, and you will be able to associate the received result with the task specified at your system.
  2. You want to associate other kinds of data at your system. For instance:
    • a keyword has id=1238 at your system,
    • a search engine id=43289,
    • a location id=97435,
    • a language id=2,
    • a user for whom you want to complete this task has id=9999.

    Since the index of a task in the data array can be specified as a string, you can create this index using any symbol as a delimiter that fits you most to send the information mentioned above as a post_id. For instance, let’s see how it will look like if we use # as a delimiter. The index that includes all necessary data will have this value 1238#43289#97435#2#9999. As a result, the request for setting of a task will look like this: "{"data":{"1238#43289#97435#2#9999":{"priority":1,"se_name":"google.co.uk","se_language":"English","loc_name_canonical":"London,England,United Kingdom","key":"online rank tracker"}}}"
    When you get the result of this task, you will be able to put in order the string to get the values you need. It will make the integration with our service easier for you.

As a response of API server you will receive JSON array in the field results of which there will be an information appropriate to the set tasks.

Description of the fields in the results array:

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of error
results_time string execution time, seconds
results_count string *number of elements in the array of results results
results array results array of tasks setting
            task_id integer unique task identifier in our system
in the future you will be able to use it within 7 days to request results of this task any time.
            status string results of this task setting
“ok” - success
“error” - error
if status=“error”, then you can see more detailed information of array error error
            error array informational array of error
only if status=“error”
the list of possible errors can be found below.
                  code integer error code
                  message string text description of error
            post_id string index in the array received in a POST request
            post_key string key received in a POST request
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            se_id integer search engine id
if status=“ok”, then this field will be always filled
You can use it for finding relations between your and our search engines.
            loc_id integer search engine location id
if status=“ok”, then this field will be always filled
You can use it for finding relations between your and our search engines.
            key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id

Possible errors codes

Error Code Meaning
404 “not found or not enough data: site” - you didn’t specify a website in the task
404 “not found or not enough data: search engine” - you’ve specified nonexistent se_id or a search engine wasn’t found by specified se_name
404 “not found or not enough data: location” - you’ve specified nonexistent loc_id or a location of a search engine wasn’t found by specified loc_name_canonical
404 “not enough data: keyword” - you didn’t specify a keyword in the task
501 “invalid ‘data’ field” - probably you haven’t passed data for the tasks in the fielddata. POST data should be represented as an array and added to the field data: array(‘data’ => $post_array_for_tasks)
501 “invalid data” - data in the field data isn’t an array with the required structure.
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get SERP HTML Completed Tasks

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/srp_html_tasks_get
    $tasks_get_result = $client->get('v2/srp_html_tasks_get');
    print_r($tasks_get_result);

    //get tasks one by one

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
response = client.get("/v2/srp_html_tasks_get")
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task srp_html_tasks_get()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/srp_html_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    Console.WriteLine(completedTask);
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void srp_html_tasks_get() throws JSONException, URISyntaxException, IOException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_html_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse completedTasksResponse = client.execute(get);
        JSONObject completedTasksObj = new JSONObject(EntityUtils.toString(completedTasksResponse.getEntity()));

        if (completedTasksObj.get("status") == "error") {
            JSONObject errorObj = completedTasksObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!completedTasksObj.get("results_count").equals(0)) {
            JSONArray results = completedTasksObj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.getJSONObject(i));
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.1104 sec.",
    "results_count": 1,
    "results": [
        {
            "status": "ok",
            "post_id": "2365896",
            "task_id": 353729730,
            "post_key": "online ranksonic",
            "key_id": 67600559,
            "se_domain": "google.co.uk",
            "se_id": 22,
            "loc_id": 1006886
        }
    ]
}

You will get the list of complete results, that you haven’t collected yet. After you collect a result the task will be removed from this list.

If you specify pingback_url or postback_url you can skip usage of srp_tasks_get to get the list of completed tasks. Our system send you GET request to the pingback_url or send POST request with results to the postback_url.

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Description of the fields in the results array:

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count string number of elements in the array of results results
results array results array of tasks
      post_id string index in the array received in a POST array
      task_id integer unique task identifier in our system
in the future you will be able to use it within 7 days to request results of this task any time
      post_key string key received in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
      key_id integer keyword id in our system
if you plan to use this keyword in the future we recommend you to save this id and use it when you set a task as key_id
      se_domain string search engine domain
      se_id integer search engine id
You can use it for finding relations between your and our search engines
      loc_id integer search engine location id
You can use it for finding relations between your and our search engines.

Get SERP HTML Results by task_id

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/srp_html_tasks_get
    $tasks_get_result = $client->get('v2/srp_html_tasks_get');
    print_r($tasks_get_result);
    if ($tasks_get_result["status"] == "ok") {
        foreach($tasks_get_result["results"] as $tasks_get_row) {
            // #2 - get result by task_id
            //GET /v2/srp_html_tasks_get/$task_id
            $serp_result = $client->get('v2/srp_html_tasks_get/'.$tasks_get_row["task_id"]);
            print_r($serp_result);

            //do something with results
        }
    }
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
completed_tasks_response = client.get("/v2/srp_html_tasks_get")
if completed_tasks_response["status"] == "error":
    print("error. Code: %d Message: %s" % (completed_tasks_response["error"]["code"], completed_tasks_response["error"]["message"]))
else:
    results = completed_tasks_response["results"]
    print(results)
    for result in results:
        srp_response = client.get("/v2/srp_html_tasks_get/%d" % (result["task_id"]))
        if srp_response["status"] == "error":
            print("error. Code: %d Message: %s" % (srp_response["error"]["code"], srp_response["error"]["message"]))
        else:
            print(srp_response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task srp_html_tasks_get_by_task_id()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/srp_html_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    var serpResponse = await httpClient.GetAsync($"v2/srp_html_tasks_get/{completedTask.task_id}");
                    var serpObj = JsonConvert.DeserializeObject<dynamic>(await serpResponse.Content.ReadAsStringAsync());
                    if (serpObj.status == "error")
                        Console.WriteLine($"error. Code: {serpObj.error.code} Message: {serpObj.error.message}");
                    foreach (var serpResult in serpObj.results)
                        Console.WriteLine(((IEnumerable<dynamic>)serpResult).First());
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void srp_html_tasks_get_by_task_id() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_html_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse completedTasksResponse = client.execute(get);
        JSONObject completedTasksObj = new JSONObject(EntityUtils.toString(completedTasksResponse.getEntity()));

        if (completedTasksObj.get("status") == "error") {
            JSONObject errorObj = completedTasksObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!completedTasksObj.get("results_count").equals(0)) {
            JSONArray results = completedTasksObj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                HttpGet getTask = new HttpGet("https://api.dataforseo.com/v2/srp_html_tasks_get/" + results.getJSONObject(i).get("task_id"));
                System.out.println(results.getJSONObject(i).get("task_id"));
                getTask.setHeader("Content-type", "application/json");
                getTask.setHeader("Authorization", "Basic " + basicAuth);
                HttpResponse serpResponse = client.execute(getTask);
                JSONObject serpObj = new JSONObject(EntityUtils.toString(serpResponse.getEntity()));
                System.out.println(serpObj.toString());
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.1766 sec.",
    "results_count": 1,
    "results": [
        {
            "post_id": "2365896",
            "task_id": 348909840,
            "keyword": "online rank checker",
            "se_domain": "google.co.uk",
            "country": "GB",
            "device": "desktop",
            "html": [
                [
                    "<!doctype html> ... </html>"
                ]
            ]
        }
    ]
}

Description of the fields for a request setting:

Name of a field Type Description
task_id string unique task identifier in our system
in the future you will be able to use it within 7 days to request results of this task any time.
param string additional parameter
allowable values:
normalized in this case an html page will be retrieved without any styles and scripts
if this parameter is not specified, you will receive a complete html page

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Description of the fields in the results array:

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count string number of elements in the array of results results
results array results array of tasks setting
      post_id string index in the array received in a POST array
      task_id integer unique task identifier in our system
in the future you will be able to use it within 7 days to request results of this task any time. You are charged for each GET request for results receiving.
      keyword string keyreceived in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
      se_domain string search engine domain
      country string ISO country code
      device string device
      html array results array
result array with html page

Possible errors codes

Error Code Meaning
102 “task in queue” - the task is being enqueued to handling, please, try again later
201 “task handed” - the task has been received and sent to handling, please, try again later
202 “in progress” - the task is in the handling process, please, try again later
404 “search engine did not return results” - SERP is empty. Check if you have added key correctly
404 “top results not found” - there is no SERP with specified parameters

Keywords Data API

Keywords Data API is a toolkit that was created for keyword selection and analysis of their efficiency. Our system uses Google AdWords API, that’s why the possibilities and limits correspond with this API. Google doesn’t return the data for keywords that are relevant to such thematics as weapon, tobacco, drugs, violence and terrorism.

Please note, if you post, for instance, 100 keywords and at least one of them is relevant to the specified thematics, the data won’t be retrieved for any of them more details can be found at Google Advertising Policies Help.

The operating principle of Keywords Data API is similar to Rank Tracker API. The main difference is that you don’t receive all complete results at once - you receive a list of task_id which results are complete, after you can receive each result separately. This is due to the fact that each of tasks has huge data amount.

Search Volume for Keyword

You can receive the search volume data for the last month, search volume trend for the last year (that will let you estimate search volume dynamics), current cost-per-click and competition value for paid search.

There are two methods to retrieve data: Live and Delayed

Live data retrieving fits perfectly in those cases if your app functionality implies supplying users with data in real-time. Using this method, you will get results within 30 seconds after the task was posted.

If you have requests that don’t demand to retrieve the data in real-time, then the delayed queue is the best solution for you. Set a task and retrieve results when our system collects them. On average it takes 15-30 minutes to receive results.

Live Data

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');

    $post_array[] = array(
    "language" => "en",
    "loc_name_canonical"=> "United States",
    "key" => "average page rpm adsense"
    );
    $post_array[] = array(
    "language" => "en",
    "loc_id" => 2840,
    "key" => "adsense blank ads how long"
    );
    $post_array[] = array(
    "language" => "en",
    "loc_name_canonical"=> "United States",
    "key" => "leads and prospects"
    );


    $sv_post_result = $client->post('v2/kwrd_sv', array('data' => $post_array));
    print_r($sv_post_result);

    //do something with results

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")

keywords_list = [
    dict(
        language="en",
        loc_name_canonical="United States",
        key="average page rpm adsense"
    ),
    dict(
        language="en",
        loc_id=2840,
        key="adsense blank ads how long"
    ),
    dict(
        language="en",
        loc_name_canonical="United States",
        key="leads and prospects"
    )
]

response = client.post("/v2/kwrd_sv", dict(data=keywords_list))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var postArray = new object[]
            {
                new { language = "en", loc_name_canonical = "United States", key = "average page rpm adsense" },
                new { language = "en", loc_id = 2840, key = "adsense blank ads how long" },
                new { language = "en", loc_name_canonical = "United States", key = "leads and prospects" }
            };
            var response = await httpClient.PostAsync("v2/kwrd_sv", new StringContent(JsonConvert.SerializeObject(new { data = postArray })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                    Console.WriteLine(result);
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_sv() throws IOException, JSONException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_sv");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        List<Map<String, Object>> postValues = new ArrayList<>();

        Map<String, Object> postObj1 = new HashMap<>();
        postObj1.put("language", "en");
        postObj1.put("loc_name_canonical", "United States");
        postObj1.put("key", "average page rpm adsense");
        postValues.add(postObj1);

        Map<String, Object> postObj2 = new HashMap<>();
        postObj2.put("language", "en");
        postObj2.put("loc_id", 2840);
        postObj2.put("key", "adsense blank ads how long");
        postValues.add(postObj2);

        Map<String, Object> postObj3 = new HashMap<>();
        postObj3.put("language", "en");
        postObj3.put("loc_name_canonical", "United States");
        postObj3.put("key", "leads and prospects");
        postValues.add(postObj3);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse response = client.execute(post);
        JSONObject obj = new JSONObject(EntityUtils.toString(response.getEntity()));

        if (obj.get("status").equals("error")) {
            System.out.println("error. Code:" + obj.getJSONObject("error").get("code") + " Message:" + obj.getJSONObject("error").get("message"));
        } else {
            JSONArray results = obj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.get(i));
            }
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "task_id": 423292503,
    "results_time": "2.1886 sec.",
    "results_count": 3,
    "results": [
        {
            "language": "en",
            "loc_id": 2840,
            "key": "leads and prospects",
            "cmp": 0.47619047619048,
            "cpc": 0,
            "sv": 10,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 10
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "adsense blank ads how long",
            "cmp": 0,
            "cpc": 0,
            "sv": 10,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 0
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 0
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 0
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "average page rpm adsense",
            "cmp": null,
            "cpc": null,
            "sv": null,
            "ms": null
        }
    ]
}

You don’t have to group keywords according to the required location/language. Send as many array elements for any language/location as you need. Our system will charge credits per each keyword in the array.

All POST data should be sent in the JSON format (UTF-8 encoding). The keywords are sent by POST method passing tasks array. The data should be specified in the data field of this POST array. We recommend to send up to 100 tasks at a time. Each array element has such structure:

Name of a field Type Description
key string keyword
required field
for instance: “rank tracker api”
loc_id integer search engine location id
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of available locations for search engines loc_id you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_id appropriate Criteria ID
loc_name_canonical string full name of a location for search engine
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of the available locations with specifying of their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_name_canonical appropriate Canonical Name
for instance: “London,England,United Kingdom”
language string language
optional field
can have the following values: “ar”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
search_partners boolean Google search partners
optional field
if you specify the true value in the field, the results will be delivered for Google and search partners. By default, search partners are not considered

As a response of API server you will receive JSON array in the field results of which there will be keywords data.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you will be able to see more detailed information about array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
task_id integer unique task identifier in our system
results_time string execution time
results_count integer number of elements in the array of results results
results array array of results
            language string language
            loc_id integer search engine location id
            key string keyword
keyword is returned decoded %## (plus symbol ‘+’ is decoded as a space character)
            cmp float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. This value will be between 0 and 1 (inclusive).
if there is no data then the value is null
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword.
if there is no data then the value is null
            sv integer search volume for the last month
represents either the (approximate) number of searches for the given keyword idea on google.com or google.com and partners, depending on the user’s targeting.
if there is no data then the value is null
            ms array monthly searches
represents the (approximated) number of searches on this keyword idea (as available for the past twelve months), targeted to the specified geographies.
if there is no data then the value is null

Possible errors codes:

Error Code Meaning
400 “post data is not valid. please check this fields: field” - please check parameters specified in the field field
404 “not found or not enough data: location” - you have specified nonexistent loc_id, or the location for the search engine wasn’t found according to your loc_name_canonical
500 “RateExceededError” - occurs when our service exceeds the Queries Per Second (QPS) limit set by Google API. Any service that works with Google API has this limit. We are working on expanding of the limits. More details about Google API limits can be found here: developers.google.com - docs/rate-limits.We recommend to process these errors (just like any other errors) and set the next task in 30 seconds if such error occurs.

Set Task

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}

$post_array = array();
$post_array["your post_id parameter here"] = array( 
    "language" => "en",
    "loc_name_canonical" => "United States",
    "key" => "best seo",
    "pingback_url" => 'https://your-server.com/your_pingback_url.php?task_id=$task_id&post_id=$post_id'
);

if (count($post_array) > 0) {
    try {
        $task_post_result = $client->post('/v2/kwrd_sv_tasks_post', array('data' => $post_array));
        print_r($task_post_result);

        //do something with post results

    } catch (RestClientException $e) {
        echo "\n";
        print "HTTP code: {$e->getHttpCode()}\n";
        print "Error code: {$e->getCode()}\n";
        print "Message: {$e->getMessage()}\n";
        print  $e->getTraceAsString();
        echo "\n";
    }
}

$client = null;
?>
from random import Random
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
rnd = Random() #you can set as "index of post_data" your ID, string, etc. we will return it with all results.
post_data = dict()
post_data[rnd.randint(1, 30000000)] = dict(    
    language="en",
    loc_name_canonical="United States",
    key="best seo"
)
response = client.post("/v2/kwrd_sv_tasks_post", dict(data=post_data))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {                    
                    language = "en",
                    loc_name_canonical = "United States",
                    key = "best seo"
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_sv_tasks_post", new StringContent(JsonConvert.SerializeObject(new {data = postObject})));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                {
                    var taskState = ((IEnumerable<dynamic>) result).First();
                    if (taskState.status == "error")
                        Console.WriteLine($"Error in task with post_id {taskState.post_id}. Code: {taskState.error.code} Message: {taskState.error.message}");
                    Console.WriteLine(taskState);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_sv_tasks_post() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_sv_tasks_post");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("language", "en");
        postObj.put("loc_name_canonical", "United States");
        postObj.put("key", "best seo");
        postValues.put(rnd.nextInt(30000000), postObj);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        //post.setHeader("Accept", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse taskPostResponse = client.execute(post);
        JSONObject obj = new JSONObject(EntityUtils.toString(taskPostResponse.getEntity()));

        if (!obj.get("results_count").equals(0)) {
            if (obj.get("results") instanceof JSONObject) {
                JSONObject results = obj.getJSONObject("results");
                Iterator<String> keys = results.keys();
                while (keys.hasNext()) {
                    String key = keys.next();
                    if (results.getJSONObject(key).get("status").equals("error")) {
                        System.out.println("Error in task with post_id " + results.getJSONObject(key).get("post_id") + ". Code: " + results.getJSONObject(key).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(key).getJSONObject("error").get("message"));
                    } else {
                        System.out.println(results.get(key));
                    }
                }
            } else {
                JSONArray results = obj.getJSONArray("results");
                for (int i = 0; i < results.length(); i++) {
                    System.out.println(results.get(i));
                }
            }
        } else if (obj.get("status").equals("error")) {
            System.out.println("error. Code:" + obj.getJSONObject("error").get("code") + " Message:" + obj.getJSONObject("error").get("message"));
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0829 sec.",
    "results_count": 1,
    "results": [
        {
            "post_id": "your post_id parameter here",
            "task_id": 218390,
            "status": "ok"
        }
    ]
}

You don’t have to group keywords according to the required location/language. Send as many array elements for any language/location as you need. Our system will charge credits per each keyword in the array.

All POST data should be sent in the JSON format (UTF-8 encoding). The keywords are sent by POST method passing tasks array. The data should be specified in the data field of this POST array. We recommend to send up to 100 tasks at a time.

You also can receive results of completed tasks using task_id or we can send them by ourselves as soon as they are ready if you specify postback_url or pingback_url when setting a task.

Each array element has such structure:

Name of a field Type Description
key string keyword
required field
loc_id integer search engine location id
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of available locations for search engines loc_id you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_id appropriate Criteria ID
loc_name_canonical string full name of a location for search engine
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of the available locations with specifying of their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_name_canonical appropriate Canonical Name
for instance: “London,England,United Kingdom”
language string language
optional field
can have the following values: “ar”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
search_partners boolean Google search partners
optional field
if you specify the true value in the field, the results will be delivered for Google and search partners. By default, search partners are not considered
postback_url string return URL for sending task results
optional field
if you specify this URL there will be no need to pick up tasks using Get Rank Tasks Results. We will send a result of a completed task by POST request for URL as soon as a task is completed.
pingback_url string notification URL of a completed task
optional field
when a task is completed we will notify you by GET request sent to the URL you have specified
you can use string ‘$task_id’ as $task_id variable and ‘$post_id’ as $post_id variable. we will set necessary values before sending of a request. for example:
  http://your-server.com/pingscript?taskId=$task_id
  http://your-server.com/pingscript?taskId=$task_id&postId=$post_id

When setting tasks, you send tasks data in the array using data field. The index of the task in this array (your post_id parameter here in examples) can be used at any time after that as the post_id field. It will be returned to you with all server responses as well as our unique task_id field. Thanks to such feature, you can use this field to associate the set tasks with identifiers at your system.

As a response of API server you will receive JSON array in the field results of which there will be an information appropriate to the set tasks.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array results array of tasks setting
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.
            post_id string index in the array received in a POST request
            status string results of this task setting
“ok” - success
“error” - error
if status=“error”, then you can see more detailed information of array error error
            error array informational array of error
only if status=“error”
the list of possible errors can be found below.
                  code integer error code
                  message string text description of error

Possible errors codes

Error Code Meaning
400 “post data is not valid. please check this fields: field” - please check parameters specified in the field field
404 “not found or not enough data: location” - you have specified nonexistent loc_id, or the location for the search engine wasn’t found according to your loc_name_canonical
404 “‘data’ field structure is invalid” - specify parameters to set a task
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get Completed Tasks

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/kwrd_sv_tasks_get
    $tasks_get_result = $client->get('v2/kwrd_sv_tasks_get');
    print_r($tasks_get_result);

    //get tasks one by one

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
response = client.get("/v2/kwrd_sv_tasks_get")
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_tasks_get()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/kwrd_sv_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    Console.WriteLine(completedTask);
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_sv_tasks_get() throws URISyntaxException, IOException, JSONException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_sv_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse response = client.execute(get);
        JSONObject obj = new JSONObject(EntityUtils.toString(response.getEntity()));

        if (obj.get("status") == "error") {
            JSONObject errorObj = obj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!obj.get("results_count").equals(0)) {
            JSONArray results = obj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.getJSONObject(i));
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0594 sec.",
    "results_count": 2,
    "results": [
        {
            "task_id": 218796,
            "post_id": "your post_id parameter here",
            "status": "ok"
        },
        {
            "task_id": 218800,
            "post_id": "your post_id parameter here",
            "status": "ok"
        }
    ]
}

You will get the list of complete results, that you haven’t collected yet. After you collect a result the task will be removed from this list.

If you specify pingback_url or postback_url you can skip usage of kwrd_sv_tasks_get to get the list of completed tasks. Our system send you GET request to the pingback_url or send POST request with results to the postback_url.

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array results array of tasks
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time
            post_id string index in the array received in a POST array
            status string result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error

Possible errors codes

Error Code Meaning
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get Results by task_id

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/kwrd_sv_tasks_get
    $tasks_get_result = $client->get('v2/kwrd_sv_tasks_get');
    print_r($tasks_get_result);
    if ($tasks_get_result["status"] == "ok") {
        foreach($tasks_get_result["results"] as $tasks_get_row) {
            // #2 - get result by task_id
            //GET /v2/kwrd_sv_tasks_get/$task_id
            $kwrd_sv_result = $client->get('v2/kwrd_sv_tasks_get/'.$tasks_get_row["task_id"]);
            print_r($kwrd_sv_result);

            //do something with results
        }
    }
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
completed_tasks_response = client.get("/v2/kwrd_sv_tasks_get")
if completed_tasks_response["status"] == "error":
    print("error. Code: %d Message: %s" % (completed_tasks_response["error"]["code"], completed_tasks_response["error"]["message"]))
else:
    results = completed_tasks_response["results"]
    print(results)
    for result in results:        
        kwrd_sv_response = client.get("/v2/kwrd_sv_tasks_get/%d" % (result["task_id"]))
        if kwrd_sv_response["status"] == "error":
            print("error. Code: %d Message: %s" % (kwrd_sv_response["error"]["code"], kwrd_sv_response["error"]["message"]))
        else:
            print(kwrd_sv_response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_tasks_get_by_task_id()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/kwrd_sv_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    var kwrdSvResponse = await httpClient.GetAsync($"v2/kwrd_sv_tasks_get/{completedTask.task_id}");
                    var kwrdSvObj = JsonConvert.DeserializeObject<dynamic>(await kwrdSvResponse.Content.ReadAsStringAsync());
                    if (kwrdSvObj.status == "error")
                        Console.WriteLine($"error. Code: {kwrdSvObj.error.code} Message: {kwrdSvObj.error.message}");
                    foreach (var kwrdSvResult in kwrdSvObj.results)
                        Console.WriteLine(((IEnumerable<dynamic>)kwrdSvResult).First());
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_sv_tasks_get_by_task_id() throws URISyntaxException, IOException, JSONException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_sv_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse completedTasksResponse = client.execute(get);
        JSONObject completedTasksObj = new JSONObject(EntityUtils.toString(completedTasksResponse.getEntity()));

        if (completedTasksObj.get("status").equals("error")) {
            JSONObject errorObj = completedTasksObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!completedTasksObj.get("results_count").equals(0)) {
            JSONArray results = completedTasksObj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                HttpGet getTask = new HttpGet("https://api.dataforseo.com/v2/kwrd_sv_tasks_get/" + results.getJSONObject(i).get("task_id"));
                getTask.setHeader("Content-type", "application/json");
                getTask.setHeader("Authorization", "Basic " + basicAuth);
                HttpResponse kwrdSvResponse = client.execute(getTask);
                JSONObject kwrdSvObj = new JSONObject(EntityUtils.toString(kwrdSvResponse.getEntity()));
                if (kwrdSvObj.get("status").equals("error")) {
                    System.out.println("error. Code: " + kwrdSvObj.getJSONObject("status").get("code") + " Message: " + kwrdSvObj.getJSONObject("status").get("message"));
                }
                System.out.println(kwrdSvObj.toString());
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0722 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 218800,
            "post_id": "your post_id parameter here",
            "status": "ok",
            "result": [
                {
                    "language": "en",
                    "loc_id": 2840,
                    "key": "best seo company",
                    "cmp": 0.3628918537802365,
                    "cpc": 30.300584,
                    "sv": 2900,
                    "ms": [
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 2400
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 2400
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 2900
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 2400
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 2400
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 2400
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 2400
                        },
                        {
                            "year": 2017,
                            "month": 5,
                            "count": 6600
                        },
                        {
                            "year": 2017,
                            "month": 4,
                            "count": 2400
                        },
                        {
                            "year": 2017,
                            "month": 3,
                            "count": 2900
                        },
                        {
                            "year": 2017,
                            "month": 2,
                            "count": 2900
                        },
                        {
                            "year": 2017,
                            "month": 1,
                            "count": 2400
                        }
                    ]
                }
            ]
        }
    ]
}

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
      task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time
      post_id string index in the array received in a POST array
      status string result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
      results array results array of tasks setting
            language string language
            loc_id integer search engine location id
            key string keyword
keyword is returned decoded %## (plus symbol ‘+’ is decoded as a space character)
            cmp float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. This value will be between 0 and 1 (inclusive).
if there is no data then the value is null
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword.
if there is no data then the value is null
            sv integer search volume for the last month
represents either the (approximate) number of searches for the given keyword idea on google.com or google.com and partners, depending on the user’s targeting.
if there is no data then the value is null
            ms array monthly searches
represents the (approximated) number of searches on this keyword idea (as available for the past twelve months), targeted to the specified geographies.
if there is no data then the value is null

Possible errors codes

Error Code Meaning
102 “task in queue” - the task is being enqueued to handling, please, try again later
201 “task handed” - the task has been received and sent to handling, please, try again later
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Bulk Keyword Search Volume

You can receive the search volume data for the last month, search volume trend for the last year (that will let you estimate search volume dynamics), current cost-per-click and competition value for paid search.

You can get the required information in a bulk for up to 700 keywords. For this, create an array of 700 keywords for the same location/language.

There are two methods to retrieve data: Live and Delayed

Live data retrieving fits perfectly in those cases if your app functionality implies supplying users with data in real-time. Using this method, you will get results within 30 seconds after the task was posted.

If you have requests that don’t demand to retrieve the data in real-time, then the delayed queue is the best solution for you. Set a task and retrieve results when our system collects them. On average it takes 15-30 minutes to receive results.

Live Data

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {

    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');

    $post_array[] = array(
        "language" => "en",
        "loc_name_canonical"=> "United States",
        "keys" => array(
            "average page rpm adsense",
            "adsense blank ads how long",
            "leads and prospects"
        )
    );


    $sv_post_result = $client->post('v2/kwrd_sv_batch', array('data' => $post_array));
    print_r($sv_post_result);

    //do something with results

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")

keyword_list = [
    dict(
        language="en",
        loc_name_canonical="United States",
        keys=[
            "average page rpm adsense",
            "adsense blank ads how long",
            "leads and prospects"
        ]
    )
]


response = client.post("/v2/kwrd_sv_batch", dict(data=keyword_list))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_batch()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var postArray = new object[]
            {
                new {
                    language = "en",
                    loc_name_canonical = "United States",
                    keys = new[]
                    {
                        "average page rpm adsense",
                        "adsense blank ads how long",
                        "leads and prospects"
                    }
                }
            };
            var response = await httpClient.PostAsync("v2/kwrd_sv_batch", new StringContent(JsonConvert.SerializeObject(new { data = postArray })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                    Console.WriteLine(result);
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_sv_batch() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_sv_batch");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("language", "en");
        postObj.put("loc_name_canonical", "United States");
        postObj.put("keys", new String[]{"average page rpm adsense", "adsense blank ads how long", "leads and prospects"});
        postValues.put(rnd.nextInt(30000000), postObj);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse response = client.execute(post);
        JSONObject obj = new JSONObject(EntityUtils.toString(response.getEntity()));

        if (obj.get("status").equals("error")) {
            System.out.println("error. Code:" + obj.getJSONObject("error").get("code") + " Message:" + obj.getJSONObject("error").get("message"));
        } else if (!obj.get("results_count").equals(0)) {
            JSONArray results = obj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.get(i));
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "task_id": 423292503,
    "results_time": "2.1886 sec.",
    "results_count": 3,
    "results": [
        {
            "language": "en",
            "loc_id": 2840,
            "key": "leads and prospects",
            "cmp": 0.47619047619048,
            "cpc": 0,
            "sv": 10,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 10
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "adsense blank ads how long",
            "cmp": 0,
            "cpc": 0,
            "sv": 10,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 0
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 0
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 0
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "average page rpm adsense",
            "cmp": null,
            "cpc": null,
            "sv": null,
            "ms": null
        }
    ]
}

If you send more than 700 keywords in one array, the number of keywords will be divided by 700 and the total charged requests rounded up.

For instance, if you send 1500 keywords in one array, the system will charge 450 credits (3 API requests * 150 credits).
If you send 300 keywords in one array, the system will charge 150 credits (one API request).
If you send 700 keywords in one array, the system will also charge 150 credits.

We recommend to send up to 2100 in one request to avoid any technical issues while retrieving the data.

All POST data should be sent in the JSON format (UTF-8 encoding). The keywords are sent by POST method passing tasks array. The data should be specified in the data field of this POST array. We recommend to send up to 100 tasks at a time. Each array element has such structure:

Name of a field Type Description
keys array array of keywords
required field
loc_id integer search engine location id
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of available locations for search engines loc_id you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_id appropriate Criteria ID
loc_name_canonical string full name of a location for search engine
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of the available locations with specifying of their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_name_canonical appropriate Canonical Name
for instance: “London,England,United Kingdom”
language string language
optional field
can have the following values: “ar”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
sort_by string column to sort the results
optional field
by default the results are sorted by “sv” field, if you don’t want to receive sorted results, specify “none” value in the field
search_partners boolean Google search partners
optional field
if you specify the true value in the field, the results will be delivered for Google and search partners. By default, search partners are not considered

As a response of API server you will receive JSON array in the field results of which there will be keywords data.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you will be able to see more detailed information about array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
task_id integer unique task identifier in our system
results_time string execution time
results_count integer number of elements in the array of results results
results array array of results
            language string language
            loc_id integer search engine location id
            key string keyword
keyword is returned decoded %## (plus symbol ‘+’ is decoded as a space character)
            cmp float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. This value will be between 0 and 1 (inclusive).
if there is no data then the value is null
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword.
if there is no data then the value is null
            sv integer search volume for the last month
represents either the (approximate) number of searches for the given keyword idea on google.com or google.com and partners, depending on the user’s targeting.
if there is no data then the value is null
            ms array monthly searches
represents the (approximated) number of searches on this keyword idea (as available for the past twelve months), targeted to the specified geographies.
if there is no data then the value is null

Possible errors codes:

Error Code Meaning
400 “post data is not valid. please check this fields: field” - please check parameters specified in the field field
404 “not found or not enough data: location” - you have specified nonexistent loc_id, or the location for the search engine wasn’t found according to your loc_name_canonical
500 “RateExceededError” - occurs when our service exceeds the Queries Per Second (QPS) limit set by Google API. Any service that works with Google API has this limit. We are working on expanding of the limits. More details about Google API limits can be found here: developers.google.com - docs/rate-limits.We recommend to process these errors (just like any other errors) and set the next task in 30 seconds if such error occurs.

Set Task

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}

$post_array = array();
$post_array["your post_id parameter here"] = array( 
    "language" => "en",
    "loc_name_canonical" => "United States",
    "keys" => array(
        "repeat customers",
        "best sleeping wireless earbuds",
        "staniel cay day trip",
        "iota hoodie",
        "monero hat"
    ),
    "pingback_url" => 'https://your-server.com/your_pingback_url.php?task_id=$task_id&post_id=$post_id'
);

if (count($post_array) > 0) {
    try {
        $task_post_result = $client->post('/v2/kwrd_sv_batch_tasks_post', array('data' => $post_array));
        print_r($task_post_result);

        //do something with post results

    } catch (RestClientException $e) {
        echo "\n";
        print "HTTP code: {$e->getHttpCode()}\n";
        print "Error code: {$e->getCode()}\n";
        print "Message: {$e->getMessage()}\n";
        print  $e->getTraceAsString();
        echo "\n";
    }
}

$client = null;
?>
from random import Random
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
post_data = dict()
post_data[rnd.randint(1, 30000000)] = dict(    
    language="en",
    loc_name_canonical="United States",
    keys=[
    "repeat customers",
    "best sleeping wireless earbuds",
    "staniel cay day trip",
    "iota hoodie",
    "monero hat"
    ]
)

response = client.post("/v2/kwrd_sv_batch_tasks_post", dict(data=post_data))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_batch_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            var postArray = new object[]
            {
                new {                    
                    language = "en",
                    loc_name_canonical = "United States",
                    keys = new[]
                    {
                        "repeat customers",
                        "best sleeping wireless earbuds",
                        "staniel cay day trip",
                        "iota hoodie",
                        "monero hat"
                    }
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_sv_batch_tasks_post", new StringContent(JsonConvert.SerializeObject(new {data = postObject})));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                {
                    var taskState = ((IEnumerable<dynamic>) result).First();
                    if (taskState.status == "error")
                        Console.WriteLine($"Error in task with post_id {taskState.post_id}. Code: {taskState.error.code} Message: {taskState.error.message}");
                    Console.WriteLine(taskState);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_sv_batch_tasks_post() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_sv_batch_tasks_post");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("language", "en");
        postObj.put("loc_name_canonical", "United States");
        postObj.put("keys", new String[]
            {
                "repeat customers",
                "best sleeping wireless earbuds",
                "staniel cay day trip",
                "iota hoodie",
                "monero hat"
            }
        );
        postValues.put(rnd.nextInt(30000000), postObj);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse response = client.execute(post);
        JSONObject obj = new JSONObject(EntityUtils.toString(response.getEntity()));

        if (!obj.get("results_count").equals(0)) {
            if (obj.get("results") instanceof JSONObject) {
                JSONObject results = obj.getJSONObject("results");
                Iterator<String> keys = results.keys();
                while (keys.hasNext()) {
                    String key = keys.next();
                    if (results.getJSONObject(key).get("status").equals("error")) {
                        System.out.println("Error in task with post_id " + results.getJSONObject(key).get("post_id") + ". Code: " + results.getJSONObject(key).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(key).getJSONObject("error").get("message"));
                    } else {
                        System.out.println(results.get(key));
                    }
                }
            } else {
                JSONArray results = obj.getJSONArray("results");
                for (int i = 0; i < results.length(); i++) {
                    System.out.println(results.get(i));
                }
            }
        } else if (obj.get("status").equals("error")) {
            System.out.println("error. Code:" + obj.getJSONObject("error").get("code") + " Message:" + obj.getJSONObject("error").get("message"));
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0855 sec.",
    "results_count": 1,
    "results": [
        {
            "post_id": "your post_id parameter here",
            "task_id": 218876,
            "status": "ok"
        }
    ]
}

If you send more than 700 keywords in one array, the number of keywords will be divided by 700 and the total charged requests rounded up.

For instance, if you send 1500 keywords in one array, the system will charge 300 credits (3 API requests * 100 credits).
If you send 300 keywords in one array, the system will charge 100 credits (one API request).
If you send 700 keywords in one array, the system will also charge 100 credits.

We recommend to send up to 2100 in one request to avoid any technical issues while retrieving the data.

All POST data should be sent in the JSON format (UTF-8 encoding). The keywords are sent by POST method passing tasks array. The data should be specified in the data field of this POST array. We recommend to send up to 100 tasks at a time.

You also can receive results of completed tasks using task_id or we can send them by ourselves as soon as they are ready if you specify postback_url or pingback_url when setting a task.

Each array element has such structure:

Name of a field Type Description
keys array array of keywords
required field
loc_id integer search engine location id
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of available locations for search engines loc_id you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_id appropriate Criteria ID
loc_name_canonical string full name of a location for search engine
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of the available locations with specifying of their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_name_canonical appropriate Canonical Name
for instance: “London,England,United Kingdom”
language string language
optional field
can have the following values: “ar”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
sort_by string column to sort the results
optional field
by default the results are sorted by “sv” field, if you don’t want to receive sorted results, specify “none” value in the field
search_partners boolean Google search partners
optional field
if you specify the true value in the field, the results will be delivered for Google and search partners. By default, search partners are not considered
postback_url string return URL for sending task results
optional field
if you specify this URL there will be no need to pick up tasks using Get Rank Tasks Results. We will send a result of a completed task by POST request for URL as soon as a task is completed.
pingback_url string notification URL of a completed task
optional field
when a task is completed we will notify you by GET request sent to the URL you have specified
you can use string ‘$task_id’ as $task_id variable and ‘$post_id’ as $post_id variable. we will set necessary values before sending of a request. for example:
  http://your-server.com/pingscript?taskId=$task_id
  http://your-server.com/pingscript?taskId=$task_id&postId=$post_id

When setting tasks, you send tasks data in the array using data field. The index of the task in this array (your post_id parameter here in examples) can be used at any time after that as the post_id field. It will be returned to you with all server responses as well as our unique task_id field. Thanks to such feature, you can use this field to associate the set tasks with identifiers at your system.

As a response of API server you will receive JSON array in the field results of which there will be an information appropriate to the set tasks.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array results array of tasks setting
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.
            post_id string index in the array received in a POST request
            status string results of this task setting
“ok” - success
“error” - error
if status=“error”, then you can see more detailed information of array error error
            error array informational array of error
only if status=“error”
the list of possible errors can be found below.
                  code integer error code
                  message string text description of error

Possible errors codes

Error Code Meaning
400 “post data is not valid. please check this fields: field” - please check parameters specified in the field field
404 “not found or not enough data: location” - you have specified nonexistent loc_id, or the location for the search engine wasn’t found according to your loc_name_canonical
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get Completed Tasks

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/kwrd_sv_batch_tasks_get
    $tasks_get_result = $client->get('v2/kwrd_sv_batch_tasks_get');
    print_r($tasks_get_result);

    //get tasks one by one

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
response = client.get("/v2/kwrd_sv_batch_tasks_get")
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_batch_tasks_get()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/kwrd_sv_batch_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    Console.WriteLine(completedTask);
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_sv_batch_tasks_get() throws URISyntaxException, IOException, JSONException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_sv_batch_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse response = client.execute(get);
        JSONObject obj = new JSONObject(EntityUtils.toString(response.getEntity()));

        if (obj.get("status").equals("error")) {
            JSONObject errorObj = obj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!obj.get("results_count").equals(0)) {
            JSONArray results = obj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.getJSONObject(i).toString());
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0599 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 218876,
            "post_id": "your post_id parameter here",
            "status": "ok"
        }
    ]
}

You will get the list of complete results, that you haven’t collected yet. After you collect a result the task will be removed from this list.

If you specify pingback_url or postback_url you can skip usage of kwrd_sv_batch_tasks_get to get the list of completed tasks. Our system send you GET request to the pingback_url or send POST request with results to the postback_url.

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array results array of tasks
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time
            post_id string index in the array received in a POST array
            status string result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error

Possible errors codes

Error Code Meaning
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get Results by task_id

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/kwrd_sv_batch_tasks_get
    $tasks_get_result = $client->get('v2/kwrd_sv_batch_tasks_get');
    print_r($tasks_get_result);
    if ($tasks_get_result["status"] == "ok") {
        foreach($tasks_get_result["results"] as $tasks_get_row) {
            // #2 - get result by task_id
            //GET /v2/kwrd_sv_batch_tasks_get/$task_id
            $kwrd_sv_batch_result = $client->get('v2/kwrd_sv_batch_tasks_get/'.$tasks_get_row["task_id"]);
            print_r($kwrd_sv_batch_result);

            //do something with results
        }
    }
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
completed_tasks_response = client.get("/v2/kwrd_sv_batch_tasks_get")
if completed_tasks_response["status"] == "error":
    print("error. Code: %d Message: %s" % (completed_tasks_response["error"]["code"], completed_tasks_response["error"]["message"]))
else:
    results = completed_tasks_response["results"]
    print(results)
    for result in results:        
        kwrd_sv_batch_response = client.get("/v2/kwrd_sv_batch_tasks_get/%d" % (result["task_id"]))
        if kwrd_sv_batch_response["status"] == "error":
            print("error. Code: %d Message: %s" % (kwrd_sv_batch_response["error"]["code"], kwrd_sv_batch_response["error"]["message"]))
        else:
            print(kwrd_sv_batch_response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_batch_tasks_get_by_task_id()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/kwrd_sv_batch_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    var kwrdSvBatchResponse = await httpClient.GetAsync($"v2/kwrd_sv_batch_tasks_get/{completedTask.task_id}");
                    var kwrdSvBatchObj = JsonConvert.DeserializeObject<dynamic>(await kwrdSvBatchResponse.Content.ReadAsStringAsync());
                    if (kwrdSvBatchObj.status == "error")
                        Console.WriteLine($"error. Code: {kwrdSvBatchObj.error.code} Message: {kwrdSvBatchObj.error.message}");
                    foreach (var kwrdSvBatchResult in kwrdSvBatchObj.results)
                        Console.WriteLine(((IEnumerable<dynamic>)kwrdSvBatchResult).First());
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_sv_batch_tasks_get_by_task_id() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_sv_batch_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse response = client.execute(get);
        JSONObject obj = new JSONObject(EntityUtils.toString(response.getEntity()));

        if (obj.get("status") == "error") {
            JSONObject errorObj = obj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!obj.get("results_count").equals(0)) {
            JSONArray results = obj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                HttpGet getTask = new HttpGet("https://api.dataforseo.com/v2/kwrd_sv_tasks_get/" + results.getJSONObject(i).get("task_id"));
                getTask.setHeader("Content-type", "application/json");
                getTask.setHeader("Authorization", "Basic " + basicAuth);
                HttpResponse kwrdSvBatchResponse = client.execute(getTask);
                JSONObject kwrdSvButchObj = new JSONObject(EntityUtils.toString(kwrdSvBatchResponse.getEntity()));
                if (kwrdSvButchObj.get("status").equals("error")) {
                    System.out.println("error. Code: " + kwrdSvButchObj.getJSONObject("status").get("code") + " Message: " + kwrdSvButchObj.getJSONObject("status").get("message"));
                }
                System.out.println(kwrdSvButchObj.toString());
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0751 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 218876,
            "post_id": "your post_id parameter here",
            "status": "ok",
            "result": [
                {
                    "language": "en",
                    "loc_id": 2840,
                    "key": "repeat customers",
                    "cmp": 0.15841979249800478,
                    "cpc": 0,
                    "sv": 390,
                    "ms": [
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 390
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 480
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 480
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 390
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 390
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 320
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 390
                        },
                        {
                            "year": 2017,
                            "month": 5,
                            "count": 390
                        },
                        {
                            "year": 2017,
                            "month": 4,
                            "count": 390
                        },
                        {
                            "year": 2017,
                            "month": 3,
                            "count": 480
                        },
                        {
                            "year": 2017,
                            "month": 2,
                            "count": 390
                        },
                        {
                            "year": 2017,
                            "month": 1,
                            "count": 480
                        }
                    ]
                },
                {
                    "language": "en",
                    "loc_id": 2840,
                    "key": "best sleeping wireless earbuds",
                    "cmp": null,
                    "cpc": null,
                    "sv": null,
                    "ms": null
                }
            ]
        }
    ]
}

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
      task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time
      post_id string index in the array received in a POST array
      status string result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
      results array results array of tasks setting
            language string language
            loc_id integer search engine location id
            key string keyword
keyword is returned decoded %## (plus symbol ‘+’ is decoded as a space character)
            cmp float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. This value will be between 0 and 1 (inclusive).
if there is no data then the value is null
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword.
if there is no data then the value is null
            sv integer search volume for the last month
represents either the (approximate) number of searches for the given keyword idea on google.com or google.com and partners, depending on the user’s targeting.
if there is no data then the value is null
            ms array monthly searches
represents the (approximated) number of searches on this keyword idea (as available for the past twelve months), targeted to the specified geographies.
if there is no data then the value is null

Possible errors codes

Error Code Meaning
102 “task in queue” - the task is being enqueued to handling, please, try again later
201 “task handed” - the task has been received and sent to handling, please, try again later
202 “in progress” - the task is in the handling process, please, try again later

Keywords for Domain

This option will select keywords for a specified domain. In addition to keyword you will also receive search volume for the last month, search volume trend for the last year (that will let you estimate search volume dynamics), current cost-per-click and competition level for paid search.

There are two methods to retrieve data: Live and Delayed

Live data retrieving fits perfectly in those cases if your app functionality implies supplying users with data in real-time. Using this method, you will get results within 30 seconds after the task was posted.

If you have requests that don’t demand to retrieve the data in real-time, then the delayed queue is the best solution for you. Set a task and retrieve results when our system collects them. On average it takes 15-30 minutes to receive results.

Live Data

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');

    $kw_get_result = $client->get('v2/kwrd_for_domain/ranksonic.com/us/en');
    print_r($kw_get_result);

    //do something with results

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
domain = "ranksonic.com"
country_code = "us"
language = "en"
response = client.get("/v2/kwrd_for_domain/%s/%s/%s" % (domain, country_code, language))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_domain()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var domain = "ranksonic.com";
            var country = "us";
            var language = "en";
            var response = await httpClient.GetAsync($"v2/kwrd_for_domain/{domain}/{country}/{language}");
            var obj = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                    Console.WriteLine(result);
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_for_domain() throws IOException, JSONException {
        HttpClient client;
        client = HttpClientBuilder.create().build();
        String domain = "ranksonic.com";
        String country = "us";
        String language = "en";
        HttpGet get = new HttpGet("https://api.dataforseo.com/v2/kwrd_for_domain/" + domain + "/" + country + "/" + language);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse response = client.execute(get);
        JSONObject obj = new JSONObject(EntityUtils.toString(response.getEntity()));

        if (obj.get("status") == "error") {
            JSONObject errorObj = obj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else {
            JSONArray results = obj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.get(i));
            }
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "task_id": 423292503,
    "results_time": "5.6869 sec.",
    "results_count": 700,
    "results": [
        {
            "language": "en",
            "loc_id": 2840,
            "key": "seo checker",
            "cmp": 0.73449937159615,
            "cpc": 268.914463,
            "sv": 3600,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 4400
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 4400
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 4400
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 3600
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 2900
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 2900
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "seo software",
            "cmp": 0.61448140900196,
            "cpc": 207.076566,
            "sv": 1600,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 1900
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 2400
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 1900
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 1600
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 1300
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 1900
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 2400
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 1300
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 1600
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 1900
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 1300
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 1300
                }
            ]
        },


        {
            "language": "en",
            "loc_id": 2840,
            "key": "check serp ranking for keyword",
            "cmp": 0.097560975609756,
            "cpc": 0,
            "sv": 10,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 40
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 50
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 20
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 20
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 10
                }
            ]
        }
    ]
}

The receiving of keywords is made by GET method with such parameters:

Name of a field Type Description
domain string domain
required field
you can also specify URL in single quotes, like
GET https://api.dataforseo.com/v2/kwrd_for_domain/'https://seo.com/page/'/us/en
country_code string ISO country code
optional field
language string language
optional field
can have the following values: “ar”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
sort_by string column to sort the results
optional field
can have the following values: “sv”, “relevance”
default value: “sv”

As a response of API server you will receive JSON array in the field results of which there will be data for the selected keywords. Maximum amount of the selected keywords is 700. Array of results is returned according to the sorted field sv.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you will be able to see more detailed information about array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
task_id integer unique task identifier in our system
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array array of results
            language string language
            loc_id integer search engine location id
            key string keyword
            cmp float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. This value will be between 0 and 1 (inclusive).
if there is no data then the value is null
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword.
if there is no data then the value is null
            sv integer search volume for the last month
represents either the (approximate) number of searches for the given keyword idea on google.com or google.com and partners, depending on the user’s targeting.
if there is no data then the value is null
            ms array monthly searches
represents the (approximated) number of searches on this keyword idea (as available for the past twelve months), targeted to the specified geographies.
if there is no data then the value is null

Possible errors codes:

Error Code Meaning
400 “post data is not valid. please check this fields: field” - please check parameters specified in the field field
500 “RateExceededError” - occurs when our service exceeds the Queries Per Second (QPS) limit set by Google API. Any service that works with Google API has this limit. We are working on expanding of the limits. More details about Google API limits can be found here: developers.google.com - docs/rate-limits.We recommend to process these errors (just like any other errors) and set the next task in 30 seconds if such error occurs.

Set Task

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}

$post_array = array();
$post_array["your post_id parameter here"] = array( 
    "domain" => "ranksonic.com",
    "country_code" => "us",
    "language" => "en",
    "sort_by" => "relevance",
    "pingback_url" => 'https://your-server.com/your_pingback_url.php?task_id=$task_id&post_id=$post_id'
);

if (count($post_array) > 0) {
    try {
        $task_post_result = $client->post('/v2/kwrd_for_domain_tasks_post', array('data' => $post_array));
        print_r($task_post_result);

        //do something with post results

    } catch (RestClientException $e) {
        echo "\n";
        print "HTTP code: {$e->getHttpCode()}\n";
        print "Error code: {$e->getCode()}\n";
        print "Message: {$e->getMessage()}\n";
        print  $e->getTraceAsString();
        echo "\n";
    }
}

$client = null;
?>
from random import Random
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
rnd = Random() #you can set as "index of post_data" your ID, string, etc. we will return it with all results.
post_data = dict()

post_data[rnd.randint(1, 30000000)] = dict(    
    domain="ranksonic.com",
    country_code="us",
    language="en",
    sort_by="relevance"
)

response = client.post("/v2/kwrd_for_domain_tasks_post", dict(data=post_data))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_domain_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {                    
                    domain = "ranksonic.com",
                    country_code = "us",
                    language = "en",
                    sort_by = "relevance"
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_for_domain_tasks_post", new StringContent(JsonConvert.SerializeObject(new {data = postObject})));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                {
                    var taskState = ((IEnumerable<dynamic>) result).First();
                    if (taskState.status == "error")
                        Console.WriteLine($"Error in task with post_id {taskState.post_id}. Code: {taskState.error.code} Message: {taskState.error.message}");
                    Console.WriteLine(taskState);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_for_domain_tasks_post() throws IOException, JSONException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_domain_tasks_post");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("domain", "ranksonic.com");
        postObj.put("country_code", "us");
        postObj.put("language", "en");
        postObj.put("sort_by", "relevance");
        postValues.put(rnd.nextInt(30000000), postObj);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse taskPostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(taskPostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            if (taskPostObj.get("results") instanceof JSONArray) {
                JSONArray results = taskPostObj.getJSONArray("results");
                for (int i = 0; i < results.length(); i++) {
                    String status = results.getJSONObject(i).get("status").toString();
                    if (status.equals("error"))
                        System.out.println("Error in task with post_id " + results.getJSONObject(i).get("post_id") + ". Code: " + results.getJSONObject(i).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(i).getJSONObject("error").get("message"));
                    else {
                        System.out.println(results.getJSONObject(i).toString());
                    }
                }
            } else {
                JSONObject results = taskPostObj.getJSONObject("results");
                Iterator<String> jkeys = results.keys();
                while (jkeys.hasNext()) {
                    String key = jkeys.next();
                    String status = results.getJSONObject(key).get("status").toString();
                    if (status.equals("error"))
                        System.out.println("Error in task with post_id " + results.getJSONObject(key).get("post_id") + ". Code: " + results.getJSONObject(key).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(key).getJSONObject("error").get("message"));
                    else {
                        System.out.println(results.getJSONObject(key).toString());
                    }
                }
            }
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0790 sec.",
    "results_count": 1,
    "results": [
        {
            "post_id": "your post_id parameter here",
            "task_id": 219163,
            "status": "ok"
        }
    ]
}

All POST data should be sent in the JSON format (UTF-8 encoding). The domains are sent by POST method passing tasks array. The data should be specified in the data field of this POST array. We recommend to send up to 100 tasks at a time.

You also can receive results of completed tasks using task_id or we can send them by ourselves as soon as they are ready if you specify postback_url or pingback_url when setting a task.

Each array element has such structure:

Name of a field Type Description
domain string domain
required field
you can also specify URL
country_code string ISO country code
optional field
language string language
optional field
can have the following values: “ar”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
sort_by string column to sort the results
optional field
can have the following values: “sv”, “relevance”
default value: “sv”
postback_url string return URL for sending task results
optional field
if you specify this URL there will be no need to pick up tasks using Get Rank Tasks Results. We will send a result of a completed task by POST request for URL as soon as a task is completed.
pingback_url string notification URL of a completed task
optional field
when a task is completed we will notify you by GET request sent to the URL you have specified
you can use string ‘$task_id’ as $task_id variable and ‘$post_id’ as $post_id variable. we will set necessary values before sending of a request. for example:
  http://your-server.com/pingscript?taskId=$task_id
  http://your-server.com/pingscript?taskId=$task_id&postId=$post_id

When setting tasks, you send tasks data in the array using data field. The index of the task in this array (your post_id parameter here in examples) can be used at any time after that as the post_id field. It will be returned to you with all server responses as well as our unique task_id field. Thanks to such feature, you can use this field to associate the set tasks with identifiers at your system.

As a response of API server you will receive JSON array in the field results of which there will be an information appropriate to the set tasks.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array results array of tasks setting
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time.
            post_id string index in the array received in a POST request
            status string results of this task setting
“ok” - success
“error” - error
if status=“error”, then you can see more detailed information of array error error
            error array informational array of error
only if status=“error”
the list of possible errors can be found below.
                  code integer error code
                  message string text description of error

Possible errors codes

Error Code Meaning
400 “post data is not valid. please check this fields: field” - please check parameters specified in the field field
404 “not found or not enough data: location” - you have specified nonexistent loc_id, or the location for the search engine wasn’t found according to your loc_name_canonical
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get Completed Tasks

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/kwrd_for_domain_tasks_get
    $tasks_get_result = $client->get('v2/kwrd_for_domain_tasks_get');
    print_r($tasks_get_result);

    //get tasks one by one

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
response = client.get("/v2/kwrd_for_domain_tasks_get")
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_domain_tasks_get()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/kwrd_for_domain_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    Console.WriteLine(completedTask);
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_for_domain_tasks_get() throws URISyntaxException, IOException, JSONException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_domain_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse taskGetResponse = client.execute(get);
        JSONObject taskGetObj = new JSONObject(EntityUtils.toString(taskGetResponse.getEntity()));

        if (taskGetObj.get("status") == "error") {
            JSONObject errorObj = taskGetObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!taskGetObj.get("results_count").equals(0)) {
            JSONArray results = taskGetObj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.getJSONObject(i));
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0979 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 254521,
            "post_id": "your post_id parameter here",
            "status": "ok"
        }
    ]
}

You will get the list of complete results, that you haven’t collected yet. After you collect a result the task will be removed from this list.

If you specify pingback_url or postback_url you can skip usage of kwrd_for_domain_tasks_get to get the list of completed tasks. Our system send you GET request to the pingback_url or send POST request with results to the postback_url.

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array results array of tasks
            task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time
            post_id string index in the array received in a POST array
            status string result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error

Possible errors codes

Error Code Meaning
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Get Results by task_id

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com', null, 'login', 'password');

    // #1 - get task_id list of ALL ready results
    //GET /v2/kwrd_for_domain_tasks_get
    $tasks_get_result = $client->get('v2/kwrd_for_domain_tasks_get');
    print_r($tasks_get_result);
    if ($tasks_get_result["status"] == "ok") {
        foreach($tasks_get_result["results"] as $tasks_get_row) {
            // #2 - get result by task_id
            //GET /v2/kwrd_for_domain_tasks_get/$task_id
            $kwrd_for_domain_result = $client->get('v2/kwrd_for_domain_tasks_get/'.$tasks_get_row["task_id"]);
            print_r($kwrd_for_domain_result);

            //do something with results
        }
    }
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
completed_tasks_response = client.get("/v2/kwrd_for_domain_tasks_get")
if completed_tasks_response["status"] == "error":
    print("error. Code: %d Message: %s" % (completed_tasks_response["error"]["code"], completed_tasks_response["error"]["message"]))
else:
    results = completed_tasks_response["results"]
    print(results)
    for result in results:        
        kwrd_for_domain_response = client.get("/v2/kwrd_for_domain_tasks_get/%d" % (result["task_id"]))
        if kwrd_for_domain_response["status"] == "error":
            print("error. Code: %d Message: %s" % (kwrd_for_domain_response["error"]["code"], kwrd_for_domain_response["error"]["message"]))
        else:
            print(kwrd_for_domain_response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_domain_tasks_get_by_task_id()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var completedTasksResponse = await httpClient.GetAsync("v2/kwrd_for_domain_tasks_get");
            var completedTasksObj = JsonConvert.DeserializeObject<dynamic>(await completedTasksResponse.Content.ReadAsStringAsync());
            if (completedTasksObj.status == "error")
                Console.WriteLine($"error. Code: {completedTasksObj.error.code} Message: {completedTasksObj.error.message}");
            else if (completedTasksObj.results_count != 0)
            {
                foreach (var result in completedTasksObj.results)
                {
                    var completedTask = ((IEnumerable<dynamic>)result).First();
                    var kwrdForDomainResponse = await httpClient.GetAsync($"v2/kwrd_for_domain_tasks_get/{completedTask.task_id}");
                    var kwrdForDomainObj = JsonConvert.DeserializeObject<dynamic>(await kwrdForDomainResponse.Content.ReadAsStringAsync());
                    if (kwrdForDomainObj.status == "error")
                        Console.WriteLine($"error. Code: {kwrdForDomainObj.error.code} Message: {kwrdForDomainObj.error.message}");
                    foreach (var kwrdForDomainResult in kwrdForDomainObj.results)
                        Console.WriteLine(((IEnumerable<dynamic>)kwrdForDomainResult).First());
                }
            }
            else
                Console.WriteLine("No completed tasks");
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_for_domain_tasks_get_by_task_id() throws URISyntaxException, IOException, JSONException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_domain_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse completedTasksResponse = client.execute(get);
        JSONObject completedTasksObj = new JSONObject(EntityUtils.toString(completedTasksResponse.getEntity()));

        if (completedTasksObj.get("status") == "error") {
            JSONObject errorObj = completedTasksObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!completedTasksObj.get("results_count").equals(0)) {
            JSONArray results = completedTasksObj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                HttpGet getKwrd = new HttpGet("https://api.dataforseo.com/v2/kwrd_for_domain_tasks_get/" + results.getJSONObject(i).get("task_id"));
                System.out.println(results.getJSONObject(i).get("task_id"));
                getKwrd.setHeader("Content-type", "application/json");
                getKwrd.setHeader("Authorization", "Basic " + basicAuth);
                HttpResponse serpResponse = client.execute(getKwrd);
                JSONObject kwrdObj = new JSONObject(EntityUtils.toString(serpResponse.getEntity()));
                System.out.println(kwrdObj.toString());
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0929 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 219066,
            "post_id": "your post_id parameter here",
            "status": "ok",
            "result": [
                {
                    "language": "en",
                    "loc_id": 2840,
                    "key": "free seo keyword generator",
                    "cmp": 0.4647887323943662,
                    "cpc": 6.850526,
                    "sv": 40,
                    "ms": [
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 70
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 40
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 30
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 30
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 20
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 30
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 30
                        },
                        {
                            "year": 2017,
                            "month": 5,
                            "count": 30
                        },
                        {
                            "year": 2017,
                            "month": 4,
                            "count": 30
                        },
                        {
                            "year": 2017,
                            "month": 3,
                            "count": 30
                        },
                        {
                            "year": 2017,
                            "month": 2,
                            "count": 50
                        },
                        {
                            "year": 2017,
                            "month": 1,
                            "count": 40
                        }
                    ]
                },
                {
                    "language": "en",
                    "loc_id": 2840,
                    "key": "free seo keyword tool",
                    "cmp": 0.33124018838304553,
                    "cpc": 3.66848,
                    "sv": 210,
                    "ms": [
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 210
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 260
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 210
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 5,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 4,
                            "count": 210
                        },
                        {
                            "year": 2017,
                            "month": 3,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 2,
                            "count": 140
                        },
                        {
                            "year": 2017,
                            "month": 1,
                            "count": 210
                        }
                    ]
                }
            ]
        }
    ]
}

As a response of API server you will receive array in the field resultsof which there will be a list of complete results.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
results_time string execution time, seconds
results_count integer number of elements in the array of results results
      task_id integer unique task identifier in our system
in the future you will be able to use it within 30 days to request results of this task any time
      post_id string index in the array received in a POST array
      status string result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information of array error error
      results array results array of tasks setting
            language string language
            loc_id integer search engine location id
            key string keyword
            cmp float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. This value will be between 0 and 1 (inclusive).
if there is no data then the value is null
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword.
if there is no data then the value is null
            sv integer search volume for the last month
represents either the (approximate) number of searches for the given keyword idea on google.com or google.com and partners, depending on the user’s targeting.
if there is no data then the value is null
            ms array monthly searches
represents the (approximated) number of searches on this keyword idea (as available for the past twelve months), targeted to the specified geographies.
if there is no data then the value is null

Possible errors codes

Error Code Meaning
102 “task in queue” - the task is being enqueued to handling, please, try again later
201 “task handed” - the task has been received and sent to handling, please, try again later
500 “internal error” - some internal error. We did our best to not let this type of error ever happen.

Keywords for Keywords

This option will select keywords suggestions for specified keywords. In addition to result keywords you will also receive search volume for the last month, search volume trend for the last year (that will let you estimate search volume dynamics), current cost-per-click and competition level for paid search.

There are two methods to retrieve data: Live and Delayed

Live data retrieving fits perfectly in those cases if your app functionality implies supplying users with data in real-time. Using this method, you will get results within 30 seconds after the task was posted.

If you have requests that don’t demand to retrieve the data in real-time, then the delayed queue is the best solution for you. Set a task and retrieve results when our system collects them. On average it takes 15-30 minutes to receive results.

Live Data

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {

    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');

    $post_array[] = array(
    "language" => "en",
    "loc_name_canonical"=> "United States",
    "keys" => array("seo", "seo agency", "seo marketing")
    );

    $kw_post_result = $client->post('v2/kwrd_for_keywords', array('data' => $post_array));
    print_r($kw_post_result);

    //do something with results

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}

$client = null;
?>
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")

keywords_list = [
    dict(
        language="en",
        loc_name_canonical="United States",
        keys=["seo", "seo agency", "seo marketing"]
    )
]
response = client.post("/v2/kwrd_for_keywords", dict(data=keywords_list))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_keywords()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };

            var postArray = new object[]
            {
                new { language = "en", loc_name_canonical = "United States", keys = new {"seo", "seo agency", "seo marketing"} }
            };
            var response = await httpClient.PostAsync("v2/kwrd_for_keywords", new StringContent(JsonConvert.SerializeObject(new { data = postArray })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                    Console.WriteLine(result);
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_for_keywords() throws URISyntaxException, IOException, JSONException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_keywords");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("language", "en");
        postObj.put("loc_name_canonical", "United States");
        postObj.put("keys", new String[]{"seo", "seo agency", "seo marketing"});
        postValues.put(rnd.nextInt(30000000), postObj);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse response = client.execute(post);
        JSONObject obj = new JSONObject(EntityUtils.toString(response.getEntity()));

        if (obj.get("status").equals("error")) {
            System.out.println("error. Code:" + obj.getJSONObject("error").get("code") + " Message:" + obj.getJSONObject("error").get("message"));
        } else if (!obj.get("results_count").equals(0)) {
            JSONArray results = obj.getJSONArray("results");
            for (int i = 0; i < results.length(); i++) {
                System.out.println(results.get(i));
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "task_id": 423292503,
    "results_time": "5.6869 sec.",
    "results_count": 700,
    "results": [
        {
            "language": "en",
            "loc_id": 2840,
            "key": "seo checker",
            "cmp": 0.73449937159615,
            "cpc": 268.914463,
            "sv": 3600,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 4400
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 4400
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 4400
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 3600
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 3600
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 2900
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 2900
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "seo software",
            "cmp": 0.61448140900196,
            "cpc": 207.076566,
            "sv": 1600,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 1900
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 2400
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 1900
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 1600
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 1300
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 1900
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 2400
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 1300
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 1600
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 1900
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 1300
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 1300
                }
            ]
        },


        {
            "language": "en",
            "loc_id": 2840,
            "key": "check serp ranking for keyword",
            "cmp": 0.097560975609756,
            "cpc": 0,
            "sv": 10,
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 40
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 50
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 20
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 20
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 10
                }
            ]
        }
    ]
}

All POST data should be sent in the JSON format (UTF-8 encoding). The keywords are sent by POST method passing tasks array. The data should be specified in the data field of this POST array. We recommend to send up to 100 tasks at a time. Each array element has such structure:

Name of a field Type Description
keys array array of keywords
required field
loc_id integer search engine location id
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of available locations for search engines loc_id you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_id appropriate Criteria ID
loc_name_canonical string full name of a location for search engine
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of the available locations with specifying of their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_name_canonical appropriate Canonical Name
for instance: “London,England,United Kingdom”
language string language
optional field
can have the following values: “ar”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
sort_by string column to sort the results
optional field
can have the following values: “sv”, “relevance”
default value: “sv”
keys_negative array array of negative keywords
optional field
These keywords will be ignored in the results array
maximum 200 elements can be specified

As a response of API server you will receive JSON array in the field results of which there will be data for the selected keywords. Maximum amount of the selected keywords is 700. Array of results is returned according to the sorted field sv.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you will be able to see more detailed information about array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
task_id integer unique task identifier in our system
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array array of results
            language string language
            loc_id integer search engine location id
            key string keyword
            cmp float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. This value will be between 0 and 1 (inclusive).
if there is no data then the value is null
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword.
if there is no data then the value is null
            sv integer search volume for the last month
represents either the (approximate) number of searches for the given keyword idea on google.com or google.com and partners, depending on the user’s targeting.
if there is no data then the value is null
            ms array monthly searches
represents the (approximated) number of searches on this keyword idea (as available for the past twelve months), targeted to the specified geographies.
if there is no data then the value is null

Possible errors codes:

Error Code Meaning
400 “post data is not valid. please check this fields: field” - please check parameters specified in the field field
500 “RateExceededError” - occurs when our service exceeds the Queries Per Second (QPS) limit set by Google API. Any service that works with Google API has this limit. We are working on expanding of the limits. More details about Google API limits can be found here: developers.google.com - docs/rate-limits.We recommend to process these errors (just like any other errors) and set the next task in 30 seconds if such error occurs.

Set Task

Instead of ‘login’ and ‘password’ use your credentials from https://my.dataforseo.com/login

<?php
require('RestClient.php');
//You can download this file from here https://api.dataforseo.com/_examples/php/_php_RestClient.zip

try {
    //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
    $client = new RestClient('https://api.dataforseo.com/', null, 'login', 'password');
} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    exit();
}

$post_array = array();
$post_array["your post_id parameter here"] = array( 
    "language" => "en",
    "loc_name_canonical" => "United States",
    "keys" => array(
        "online rank checker",
        "best seo"
    ),
    "pingback_url" => 'https://your-server.com/your_pingback_url.php?task_id=$task_id&post_id=$post_id'
);

if (count($post_array) > 0) {
    try {
        $task_post_result = $client->post('/v2/kwrd_for_keywords_tasks_post', array('data' => $post_array));
        print_r($task_post_result);

        //do something with post results

    } catch (RestClientException $e) {
        echo "\n";
        print "HTTP code: {$e->getHttpCode()}\n";
        print "Error code: {$e->getCode()}\n";
        print "Message: {$e->getMessage()}\n";
        print  $e->getTraceAsString();
        echo "\n";
    }
}

$client = null;
?>
from random import Random
from client import RestClient
#You can download this file from here https://api.dataforseo.com/_examples/python/_python_Client.zip

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
rnd = Random() #you can set as "index of post_data" your ID, string, etc. we will return it with all results.
post_data = dict()
post_data[rnd.randint(1, 30000000)] = dict(    
    language="en",
    loc_name_canonical="United States",
    keys=[
        "online rank checker",
        "best seo"
    ]
)

response = client.post("/v2/kwrd_for_keywords_tasks_post", dict(data=post_data))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_keywords_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),

                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            {
                new {                    
                    language = "en",
                    loc_name_canonical = "United States",
                    keys = new[]
                    {
                        "online rank checker",
                        "best seo"
                    }
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_for_keywords_tasks_post", new StringContent(JsonConvert.SerializeObject(new {data = postObject})));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                {
                    var taskState = ((IEnumerable<dynamic>) result).First();
                    if (taskState.status == "error")
                        Console.WriteLine($"Error in task with post_id {taskState.post_id}. Code: {taskState.error.code} Message: {taskState.error.message}");
                    Console.WriteLine(taskState);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_for_keywords_tasks_post() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_keywords_tasks_post");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        Map<Integer, Map<String, Object>> postValues = new HashMap<>();

        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("language", "en");
        postObj.put("loc_name_canonical", "United States");
        postObj.put("keys", new String[]{"online rank checker", "best seo"});
        postValues.put(rnd.nextInt(30000000), postObj);

        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());
        input.setContentType("application/json");
        post.setHeader("Content-type", "application/json");
        post.setHeader("Authorization", "Basic " + basicAuth);
        post.setEntity(input);
        HttpResponse taskPostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(taskPostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            if (taskPostObj.get("results") instanceof JSONArray) {
                JSONArray results = taskPostObj.getJSONArray("results");
                for (int i = 0; i < results.length(); i++) {
                    String status = results.getJSONObject(i).get("status").toString();
                    if (status.equals("error"))
                        System.out.println("Error in task with post_id " + results.getJSONObject(i).get("post_id") + ". Code: " + results.getJSONObject(i).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(i).getJSONObject("error").get("message"));
                    else {
                        System.out.println(results.getJSONObject(i).toString());
                    }
                }
            } else {
                JSONObject results = taskPostObj.getJSONObject("results");
                Iterator<String> jkeys = results.keys();
                while (jkeys.hasNext()) {
                    String key = jkeys.next();
                    String status = results.getJSONObject(key).get("status").toString();
                    if (status.equals("error"))
                        System.out.println("Error in task with post_id " + results.getJSONObject(key).get("post_id") + ". Code: " + results.getJSONObject(key).getJSONObject("error").get("code") + " Message: " + results.getJSONObject(key).getJSONObject("error").get("message"));
                    else {
                        System.out.println(results.getJSONObject(key).toString());
                    }
                }
            }
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0784 sec.",
    "results_count": 1,
    "results": [
        {
            "post_id": "your post_id parameter here",
            "task_id": 219428,
            "status": "ok"
        }
    ]
}

All POST data should be sent in the JSON format (UTF-8 encoding). The keywords are sent by POST method passing tasks array. The data should be specified in the data field of this POST array. We recommend to send up to 100 tasks at a time.

You also can receive results of completed tasks using task_id or we can send them by ourselves as soon as they are ready if you specify postback_url or pingback_url when setting a task.

Each array element has such structure:

Name of a field Type Description
keys array array of keywords
required field
loc_id integer search engine location id
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of available locations for search engines loc_id you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_id appropriate Criteria ID
loc_name_canonical string full name of a location for search engine
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of the available locations with specifying of their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_name_canonical appropriate Canonical Name
for instance: “London,England,United Kingdom”
language string language
optional field
can have the following values: “ar”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
sort_by string column to sort the results
optional field
can have the following values: “sv”, “relevance”
default value: “sv”
keys_negative array array of negative keywords
optional field
These keywords will be ignored in the results array
maximum 200 elements can be specified
<