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.
PHP DataForSEO Client Alternate PHP Client. Author Vitaliy Lyabakh - jovixv
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. SERP reviews provides you with users’ reviews of a specific place (restaurant, shop, etc.).

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:’, ‘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 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 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_stat": [],
                    "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_stat": [],
                    "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_stat": {
                        "rating": 4.2,
                        "rating_type": "stars",
                        "rating_max": 5,
                        "votes": 23
                    },
                    "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_stat": [],
                    "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 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_stat array information about the reviews element of a result
empty array if result does not have a reviews element
                  rating integer/float rating
the popularity rate based on reviews and displayed in the SERPs
                  rating_type string measurement units
shows which measurement units are used in the rating field
there are two possible options: stars, percents
                  rating_max integer maximum value for a rating
                  votes integer number of feedbacks
            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_stat array information about the reviews element of a result
empty array if result does not have a reviews element
                  rating integer/float rating
the popularity rate based on reviews and displayed in the SERPs
                  rating_type string measurement units
shows which measurement units are used in the rating field
there are two possible options: stars, percents
                  rating_max integer maximum value for a rating
                  votes integer number of feedbacks
            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:’, ‘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 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 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 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

Setting Extra 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_extra_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_extra_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_extra_tasks_post/$data
            // $tasks_data must by array with key 'data'
            $task_post_result = $client->post('v2/srp_extra_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_extra_tasks_post/$data
        // $tasks_data must by array with key 'data'
        $task_post_result = $client->post('v2/srp_extra_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_extra_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_extra_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_extra_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_extra_tasks_post() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_extra_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 the data included in the POST request should be in the JSON format (UTF-8 encoding). The tasks shall be set through the POST method, by placing the tasks array into the data field. It is not recommended to set more than 100 tasks at once due to the different task variations you are likely to use. Note that the usage of the url field slows down the tasks processing. On the contrary, by using system identifiers (se_id, loc_id, key_id), you can accelerate the tasks processing and set more than 100 tasks at once.

You can get the completed task results via the unique task_id. Alternatively, you may indicate the pingback_url or postback_url to get task results send to a specific url.

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
currently available only for “google desktop” and “google mobile” . to get se_id for “google desktop” and “google mobile” you must choose a search engine without any additional the words (like “ maps”, “ map pack”, “ shopping”) included into the “se_name”
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”
currently available only for “google desktop” and “google mobile” . to get se_name for “google desktop” and “google mobile” you must choose a search engine without any additional the words (like “ maps”, “ map pack”, “ shopping”) included into the “se_name”
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:’, ‘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.

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 array results array of tasks setting
            task_id integer unique task identifier in our system
you can use task_id to request task results any time within the next 30 days.
            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 Extra 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_extra_tasks_get
    $tasks_get_result = $client->get('v2/srp_extra_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_extra_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_extra_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_extra_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_extra_tasks_get() throws JSONException, URISyntaxException, IOException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_extra_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 can get the list of completed tasks that have not been collected yet. Note that all collected results are automatically erased from the list.

By indicating the pingback_url or the postback_url you get the list of completed tasks to a specific url, avoiding the extra srp_extra_tasks_get command. GET requests will be sent to the pingback_url, POST requests will be sent to the postback_url.

The list of completed results will be enclosed in the results field of the API response array.

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 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 Extra 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_extra_tasks_get
    $tasks_get_result = $client->get('v2/srp_extra_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_extra_tasks_get/$task_id
            $serp_result = $client->get('v2/srp_extra_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_extra_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_extra_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_extra_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_extra_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_extra_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_extra_tasks_get_by_task_id() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_extra_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_extra_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.1376 sec.",
    "results_count": 104,
    "results": [
        {
            "task_id": 629265414,
            "se_id": 14,
            "loc_id": 2840,
            "key_id": 4342117,
            "post_id": "here is supposed to be your post ID 1",
            "post_key": "bill gates",
            "result_se_check_url": "https:\/\/google.com\/search?q=bill%20gates&hl=en&gl=US&gws_rd=cr&uule=w+CAIQIFISCQs2MuSEtepUEUK33kOSuTsc",
            "result_date": "2018-05-22 12:27:21 +00:00",
            "result_spell": "",
            "result_extra": "top_stories,twitter,people_also_ask,knowledge_graph,videos",
            "result_serp_count": 450000000,
            "result": {
                "left": [
                    {
                        "type": "top_stories",
                        "position": 1,
                        "items": [
                            {
                                "url": "http:\/\/www.businessinsider.com\/bill-gates-summer-reading-recommendations-2018-5",
                                "title": "These are the 5 books Bill Gates recommends you read this summer"
                            },
                            {
                                "url": "https:\/\/qz.com\/1282604\/your-summer-reading-list-provided-by-bill-gates-2\/",
                                "title": "Your summer reading list, provided by Bill Gates"
                            },
                            {
                                "url": "https:\/\/www.cnbc.com\/2018\/05\/22\/bill-gates-is-betting-on-this-synthetic-biology-start-up.html",
                                "title": "Why Bill Gates is betting on a start-up that prints synthetic DNA"
                            }
                        ]
                    },
                    {
                        "type": "organic",
                        "position": 2,
                        "featured_snippet": false,
                        "image": false,
                        "video": false,
                        "url": "https:\/\/en.wikipedia.org\/wiki\/Bill_Gates",
                        "title": "Bill Gates - Wikipedia",
                        "snippet": "William Henry Gates III (born October 28, 1955) is an American business magnate, investor, author, philanthropist, humanitarian, and principal founder of ...",
                        "snippet_extra": "",
                        "links": [],
                        "stat": {
                            "rating": 4.5,
                            "rating_max": 5
                        }
                    },
                    {
                        "type": "twitter",
                        "position": 3,
                        "url": "https://twitter.com/BillGates",
                        "title": "Bill Gates (@BillGates) · Twitter",
                        "items": [
                            {
                                "url": "https:\/\/twitter.com\/BillGates\/status\/998593941762199552",
                                "tweet": "From Lincoln to Leonardo, I hope you enjoy my summer reading list. b-gat.es\/2s4hobZ",
                                "date": "20 hours ago"
                            },
                            {
                                "url": "https:\/\/twitter.com\/BillGates\/status\/997168620802199552",
                                "tweet": "At @MDCollege, smarter advising is helping students go further faster. pic.twitter.com\/iWuEG8B…",
                                "date": "5 days ago"
                            },
                            {
                                "url": "https:\/\/twitter.com\/BillGates\/status\/997084318982901760",
                                "tweet": "Glad to see this story told. I’m always inspired by the local leaders and health workers involved in the fight to #endpolio. b-gat.es\/2rLwl29",
                                "date": "5 days ago"
                            },
                            {
                                "url": "https:\/\/twitter.com\/BillGates\/status\/996862856883826690",
                                "tweet": "In the early days of Microsoft, I felt pretty confident about my coding skills, but I had a lot to learn about management. I wish I had @johndoerr’s new book back then. b-gat.es\/2GoSeZQ",
                                "date": "6 days ago"
                            },
                            {
                                "url": "https:\/\/twitter.com\/BillGates\/status\/996793962793848832",
                                "tweet": "France has been a leading champion in the fight against HIV\/AIDS, TB, and malaria.  Their generosity has helped us make terrific progress. twitter.com\/EmmanuelMac…",
                                "date": "6 days ago"
                            }
                        ]
                    },
                    {
                        "type": "local_pack",
                        "position": 4,                        
                        "title": "Pizza Express",
                        "snippet": "Longtime pizza chain known for delivery",
                        "phone": "586-235-584",
                        "rating": 3.8,
                        "rating_type": "stars",
                        "rating_max": 5,
                        "url": "",
                        "paid": true
                    },
                    {
                        "type": "local_pack",
                        "position": 5,
                        "title": "Pizza Pilgrims",
                        "snippet": "Retro-style slice & pie joint",
                        "phone": "",
                        "rating": 4,
                        "rating_type": "stars",
                        "rating_max": 5,
                        "url": "",
                        "paid": false
                    },
                    {
                        "type": "local_pack",
                        "position": 6,
                        "title": "Pizza Hut Restaurants",
                        "snippet": "Thin-crust pizzas & Stone Street seating",
                        "phone": "",
                        "rating": 4.3,
                        "rating_type": "stars",
                        "rating_max": 5,
                        "url": "",
                        "paid": false
                    },                    
                    {
                        "type": "images",
                        "position": 7,
                        "url": "https://www.google.com/search?q=search+volume&num=100&hl=en&gl=US&tbm=isch&tbo=u&source=univ&sa=X&ved=2ahUKEwjnl5PpgL_cAhVBElAKHTOYB_cQsAR6BAhSEAE",
                        "title": "Images for search volume",
                        "items": [
                            {
                                "url": "https://www.wordstream.com/blog/ws/2017/01/23/keyword-search-volume",
                                "alt": "Image result for search volume"
                            },
                            {
                                "url": "https://searchengineland.com/importance-monthly-versus-rolling-average-search-volume-225179",
                                "alt": "Image result for search volume"
                            },
                            {
                                "url": "https://ahrefs.com/blog/keyword-search-volume/",
                                "alt": "Image result for search volume"
                            }
                        ]
                    },
                    {
                        "type": "organic",
                        "position": 8,
                        "featured_snippet": false,
                        "image": false,
                        "video": false,
                        "url": "https:\/\/www.entrepreneur.com\/article\/197526",
                        "title": "Bill Gates Biography - Entrepreneur",
                        "snippet": "Bill Gates. Co-founder of Microsoft Corp. Founded: 1975. \"Ultimately, the PC will be a window to everything people are interested in-and everything we need to ...",
                        "snippet_extra": "",
                        "links": [],
                        "stat": {
                            "rating": 4.5,
                            "rating_max": 5
                        }
                    },
                    {
                        "type": "organic",
                        "position": 9,
                        "featured_snippet": false,
                        "image": false,
                        "video": false,
                        "url": "https:\/\/www.forbes.com\/profile\/bill-gates\/",
                        "title": "Bill Gates - Forbes",
                        "snippet": "With his wife Melinda, Bill Gates chairs the Bill & Melinda Gates Foundation, the world's largest private charitable foundation. The foundation works to save lives ...",
                        "snippet_extra": "",
                        "links": [],
                        "stat": []
                    },
                    {
                        "type": "featured_snippet",
                        "position": 10,
                        "url": "https://www.myprotein.com/thezone/nutrition/pre-workout-foods/",
                        "title": "Top 10 Pre Workout Foods - Myprotein",
                        "snippet": "Eating a banana pre-workout is the perfect way to boost your glycogen stores and increase blood sugar levels.Chicken, Rice &amp; Vegetables. ... Greek Yogurt and Dried Fruit. ... Porridge and Oatmeal.Fruit Smoothies.Wholegrain Bread, Sweet Potato and Brown Rice. ... Apple Wedges and Peanut Butter.Omelette.Homemade Protein Bars.More items...",
                        "table": {
                            "table_header": [
                              "Rank",
                              "Country",
                              "GDP (US$MM)"
                            ],
                            "table_data": [
                                [
                                "1",
                                "United States",
                                "19,390,600"
                                ],
                                [
                                "—",
                                "European Union",
                                "17,308,862"
                                ],
                                [
                                "2",
                                "China",
                                "12,014,610"
                                ],
                                [
                                "3",
                                "Japan",
                                "4,872,135"
                                ]
                            ]
                        }
                    },
                    {
                        "type": "people_also_ask",
                        "position": 11,
                        "items": [
                            "Who is the richest person in the world today?",
                            "How many cars does Bill Gates?",
                            "When was Bill Gates born and died?",
                            "Is Bill Gates?"
                        ]
                    },
                    {
                        "type": "organic",
                        "position": 12,
                        "featured_snippet": false,
                        "image": false,                        
                        "video": false,
                        "url": "https:\/\/www.gatesfoundation.org\/",
                        "title": "Bill & Melinda Gates Foundation",
                        "snippet": "We seek to unlock the possibility inside every individual. We see equal value in all lives. And so we are dedicated to improving the quality of life for individuals ...",
                        "snippet_extra": "",
                        "links": [],
                        "stat": []
                    },
                    {
                        "type": "app",
                        "position": 13,
                        "items": [
                            {
                                "url": "https://play.google.com/store/apps/details?id=com.rovio.angrybirds&amp;hl=en_US&amp;referrer=utm_source%3Dgoogle%26utm_medium%3Dorganic%26utm_term%3Dangry+birds&amp;pcampaignid=APPU_1_8dheW9-JG4T85gLY05XgBw",
                                "title": "Angry Birds Classic",
                                "snippet": "",
                                "price": "Free"
                            },
                            {
                                "url": "https://play.google.com/store/apps/details?id=com.rovio.baba&amp;hl=en_US&amp;referrer=utm_source%3Dgoogle%26utm_medium%3Dorganic%26utm_term%3Dangry+birds&amp;pcampaignid=APPU_1_8dheW9-JG4T85gLY05XgBw",
                                "title": "Angry Birds 2",
                                "snippet": "",
                                "price": "Free"
                            },
                            {
                                "url": "https://play.google.com/store/apps/details?id=com.rovio.angrybirds&amp;hl=en&amp;referrer=utm_source%3Dgoogle%26utm_medium%3Dorganic%26utm_term%3Dangry+birds&amp;pcampaignid=APPU_1_8dheW9-JG4T85gLY05XgBw",
                                "title": "Angry Birds Classic",
                                "snippet": "",
                                "price": "Free"
                            }
                        ]
                    },
                    {
                        "type": "shopping",
                        "position": 14,
                        "title": "See DJI drones Phantom 4",
                        "items": [
                            {
                                "title": "DJI - Phantom 4 Pro Quadcopter - White",
                                "url": "https://www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwit-a_ZrsncAhWBRIYKHVqdDC8YABADGgJ2dQ&ohost=www.google.com&cid=CAESEeD2TJLZEEFtglErOeHihIjI&sig=AOD64_2fMvHZkISwzvLaq0IzQ9as_Rr9lQ&ctype=5&q=&ved=0ahUKEwiywqjZrsncAhXImVkKHSp5DH4Q9aACCDI&adurl=",
                                "price": "$1,499.99",
                                "source": "Best Buy"
                            },
                            {
                                "title": "Case Club DJI Phantom 4 Compact Drone Case",
                                "url": "https://www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwit-a_ZrsncAhWBRIYKHVqdDC8YABAFGgJ2dQ&ohost=www.google.com&cid=CAESEeD2TJLZEEFtglErOeHihIjI&sig=AOD64_06CGFLjkrAKAIsMsLXMubmtkaO3A&ctype=5&q=&ved=0ahUKEwiywqjZrsncAhXImVkKHSp5DH4Qww8INw&adurl=",
                                "price": "$129.95",
                                "source": "Case Club"
                            },
                            {
                                "title": "DJI Phantom 4 Quadcopter Drone FPV Virtual Reality Experience w/ Hardshell Backpack",
                                "url": "https://www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwit-a_ZrsncAhWBRIYKHVqdDC8YABAHGgJ2dQ&ohost=www.google.com&cid=CAESEeD2TJLZEEFtglErOeHihIjI&sig=AOD64_15G0VZmDqYvzfro9BiC08HEzSQMQ&ctype=5&q=&ved=0ahUKEwiywqjZrsncAhXImVkKHSp5DH4Qww8IPA&adurl=",
                                "price": "$899.00",
                                "source": "BeachCamera...."
                            }
                        ]
                    },
                    {
                        "type": "answer_box",
                        "position": 15,
                        "text": [
                            "https://www.youtube.com/watch?v=-d7eYGLaiFk",
                            "OJO NGUBER WELAS - NELLA KHARISMA - YouTube",
                            "Artis",
                            "Nella Kharisma",
                            "Album",
                            "Melon Best Nella - Rupo Lan Dunyo",
                            "Dirilis",
                            "2016"
                        ],
                        "links": [
                            {
                                "url": "https://www.youtube.com/watch?v=-d7eYGLaiFk",
                                "anchor": "OJO NGUBER WELAS - NELLA KHARISMA - YouTube"
                            }
                        ]
                    },
                    {
                        "type": "map",
                        "position": 16,
                        "url": "https://www.google.com/maps/place/Andes/data=!4m2!3m1!1s0x968792fc5a4e9d2f:0x8b16530d02147954?hl=en&sa=X&ved=2ahUKEwjhw_q_sMncAhXGqFkKHY3cCDYQ8gEwAHoECAQQAQ",
                        "title": "Andes"
                    },
                    {
                        "type": "video",
                        "position": 17,
                        "items": [
                            {
                                "url": "https://www.noticiasagricolas.com.br/videos/boi/218168-entrevista-com-frederico-borges-stella-presidente-do-sindicato-rural-de-aquidauana-ms.html",
                                "title": "Preços da arroba do boi em Aquidauana-MS reagem com recuo da oferta, mas \nainda estão abaixo das necessidades dos pecuaristas",
                                "source": "Notícias Agrícolas"
                            },
                            {
                                "url": "http://g1.globo.com/mato-grosso-do-sul/mstv-1edicao/videos/t/edicoes/v/jovem-confessa-que-matou-e-congelou-corpo-de-idoso-em-aquidauana/6853090/",
                                "title": "Jovem confessa que matou e congelou corpo de idoso em ...",
                                "source": "G1 - Globo.com"
                            },
                            {
                                "url": "http://g1.globo.com/mato-grosso-do-sul/mstv-1edicao/videos/v/aquidauana-tem-casas-alagadas-e-rodovia-interditada/6517826/",
                                "title": "Aquidauana tem casas alagadas e rodovia interditada - G1 Mato ...",
                                "source": "G1 - Globo.com"
                            }
                        ]
                    },
                    {
                        "type": "google_flights",
                        "position": 18,
                        "title": "Flights from London, United Kingdom (all airports) to Berlin, Germany (all airports)",
                        "url": "https://www.google.com/flights?num=100&hl=en&source=flun&lite=0&uitype=cuAA&tfs=CAEQAhooEgoyMDE4LTA5LTIwagwIAhIIL20vMDRqcGxyDAgCEggvbS8wMTU2cRooEgoyMDE4LTA5LTIzagwIAhIIL20vMDE1NnFyDAgCEggvbS8wNGpwbA&sa=X&ved=2ahUKEwjigrv43MncAhWLxKYKHbGMB7sQuRUwAHoECAYQAw",
                        "items": [
                            {
                                "url": "https://www.google.com/flights?num=100&amp;hl=en&amp;source=flun&amp;lite=0&amp;uitype=cuAA&amp;tfs=CAEQAhouEgoyMDE4LTA5LTIwKAAyAkZSagwIAhIIL20vMDRqcGxyDAgCEggvbS8wMTU2cRouEgoyMDE4LTA5LTI0KAAyAkZSagwIAhIIL20vMDE1NnFyDAgCEggvbS8wNGpwbA&amp;sa=X&amp;ved=2ahUKEwjXwufGzr_cAhUK66QKHcaOBboQ1RUoADAAegQIBBAQ",
                                "description": "Ryanair     1h 50m  Non-stop     from €66"
                            },
                            {
                                "url": "https://www.google.com/flights?num=100&amp;hl=en&amp;source=flun&amp;lite=0&amp;uitype=cuAA&amp;tfs=CAEQAhouEgoyMDE4LTA5LTIwKAAyAlUyagwIAhIIL20vMDRqcGxyDAgCEggvbS8wMTU2cRouEgoyMDE4LTA5LTI0KAAyAlUyagwIAhIIL20vMDE1NnFyDAgCEggvbS8wNGpwbA&amp;sa=X&amp;ved=2ahUKEwjXwufGzr_cAhUK66QKHcaOBboQ1RUoATAAegQIBBAR",
                                "description": "easyJet     1h 50m  Non-stop     from €74"
                            },
                            {
                                "url": "https://www.google.com/flights?num=100&amp;hl=en&amp;source=flun&amp;lite=0&amp;uitype=cuAA&amp;tfs=CAEQAhouEgoyMDE4LTA5LTIwKAAyAkVXagwIAhIIL20vMDRqcGxyDAgCEggvbS8wMTU2cRouEgoyMDE4LTA5LTI0KAAyAkVXagwIAhIIL20vMDE1NnFyDAgCEggvbS8wNGpwbA&amp;sa=X&amp;ved=2ahUKEwjXwufGzr_cAhUK66QKHcaOBboQ1RUoAjAAegQIBBAS",
                                "description": "Eurowings     1h 50m  Non-stop     from €119"
                            }
                        ]
                    },
                   {
                        "type": "jobs",
                        "position": 19,
                        "title": "Jobs Near Philadelphia, PA",
                        "url": "",
                        "items": [
                            {
                                "url": "https://www.google.com.ua/search?hl=en&ei=zOxVW8m8F6rM6ATM4YaACw&q=philadelphia+department+of+health+jobs++++++++++++++++++++++++&oq=philadelphia+department+of+health+jobs++++++++++++++++++++++++&gs_l=psy-ab.12..0i22i30k1l3.13420.13420.0.14496.1.1.0.0.0.0.96.96.1.1.0....0...1c.1.64.psy-ab..0.1.95....0.fnNOCW1bsw4&ibp=htl;jobs#htidocid=CPe0N2zxBNIkWYd4AAAAAA%3D%3D",
                                "snippet": "Public Health Management Corporation",
                                "author": "via ZipRecruiter",
                                "date": "Over 1 month ago",
                                "type": "Contractor"
                            },
                            {
                                "url": "https://www.google.com.ua/search?hl=en&ei=zOxVW8m8F6rM6ATM4YaACw&q=philadelphia+department+of+health+jobs++++++++++++++++++++++++&oq=philadelphia+department+of+health+jobs++++++++++++++++++++++++&gs_l=psy-ab.12..0i22i30k1l3.13420.13420.0.14496.1.1.0.0.0.0.96.96.1.1.0....0...1c.1.64.psy-ab..0.1.95....0.fnNOCW1bsw4&ibp=htl;jobs#htidocid=oR8qq-x07ejC09RFAAAAAA%3D%3D",
                                "snippet": "Temple University College of Public Health",
                                "author": "via ChronicleVitae",
                                "date": "4 days ago",
                                "type": "Full-time"
                            },
                            {
                                "url": "https://www.google.com.ua/search?hl=en&ei=zOxVW8m8F6rM6ATM4YaACw&q=philadelphia+department+of+health+jobs++++++++++++++++++++++++&oq=philadelphia+department+of+health+jobs++++++++++++++++++++++++&gs_l=psy-ab.12..0i22i30k1l3.13420.13420.0.14496.1.1.0.0.0.0.96.96.1.1.0....0...1c.1.64.psy-ab..0.1.95....0.fnNOCW1bsw4&ibp=htl;jobs#htidocid=ijfp0BQIh6eWdTolAAAAAA%3D%3D",
                                "snippet": "Pepper Hamilton",
                                "author": "via Glassdoor",
                                "date": "27 days ago",
                                "type": "Full-time"
                            }
                        ]
                    },
                    {
                        "type": "carousel",
                        "position": 20,
                        "title": "Backup Software",
                        "items": [
                            {
                                "title": "Backup and RestoreProprietary software"
                            },
                            {
                                "title": "Acronis True ImageProprietary software"
                            },
                            {
                                "title": "Macrium ReflectFreeware"
                            },
                            {
                                "title": "System Restore"
                            }
                        ]
                    },
                    {
                        "type": "organic",
                        "position": 99,
                        "featured_snippet": false,
                        "image": true,
                        "video": false,
                        "url": "https://www.microsoft.com/en-us/store/b/home",
                        "title": "Microsoft Store Online",
                        "snippet": "At Microsoft our mission and values are to help people and businesses throughout the world realize their full potential.",
                        "snippet_extra": "",
                        "links": [
                            {
                                "title": "Microsoft Store Online",
                                "url": "https://www.microsoft.com/en-us/store/b/home",
                                "snippet": "Microsoft Store OnlinePCs - Xbox - Xbox Games - Download Windows 10 - ..."
                            },
                            {
                                "title": "Windows 10",
                                "url": "https://www.microsoft.com/en-us/windows",
                                "snippet": "Windows 10Windows 10 unveils new innovations & is better than ever ..."
                            }
                        ],
                        "stat": []
                    },
                    {
                        "type": "paid",
                        "position": 100,
                        "url": "https://www.booking.com/city/gb/london.html",
                        "title": "2880 Hotels in London | Lowest Price Guarantee | booking.com",
                        "snippet_row1": "Book for Tomorrow",
                        "snippet_row2": "",
                        "links": [],
                        "stat": []
                    },
                    {
                        "type": "organic",
                        "position": 101,
                        "featured_snippet": false,
                        "image": false,                        
                        "video": false,
                        "url": "https:\/\/blogs.scientificamerican.com\/observations\/bill-gates-in-search-of-nuclear-nirvana\/",
                        "title": "Bill Gates in Search of Nuclear Nirvana - Scientific American Blog ...",
                        "snippet": "May 2, 2018 - Bill Gates originally became famous (and rich) for co-founding Microsoft; more recently, he's become better known, through the Bill and Melinda ...",
                        "snippet_extra": "",
                        "links": [],
                        "stat": []
                    },
                    {
                        "type": "organic",
                        "position": 102,
                        "featured_snippet": false,
                        "image": false,                        
                        "video": false,
                        "url": "https:\/\/www.recode.net\/2018\/5\/14\/17350538\/john-doerr-measure-what-matters-book-kleiner-perkins-okrs-kara-swisher-teddy-schleifer-podcast",
                        "title": "Kleiner Perkins' John Doerr explains how to run your company like Bill ...",
                        "snippet": "May 14, 2018 - ... (in which he was an early investor), the Bill & Melinda Gates Foundation and the One Campaign, a nonprofit founded by U2 frontman Bono.",
                        "snippet_extra": "",
                        "links": [],
                        "stat": []
                    },
                    {
                        "type": "related_search",
                        "position": 103,
                        "title": "airports in berlin",
                        "items": [
                            "Berlin Schönefeld Airport",
                            "Berlin Brandenburg Airport",
                            "Berlin Tegel Airport",
                            "Berlin Tempelhof Airport",
                            "Berlin Hauptbahnhof",
                            "RAF Gatow",
                            "Johannisthal Air Field"
                        ]
                    },
                    {
                        "type": "related_search",
                        "position": 104,
                        "title": "european airports",
                        "items": [
                            "London Stansted Airport",
                            "Manchester Airport",
                            "London City Airport",
                            "Luton Airport",
                            "Keflavík International Airport",
                            "Berlin Schönefeld Airport",
                            "Berlin Tegel Airport"
                        ]
                    },
                    {
                        "type": "related",
                        "position": 105,
                        "items": [
                            "london to berlin flight time",
                            "cheapest time to fly to berlin",
                            "easyjet flights to berlin",
                            "flight to berlin germany",
                            "london to berlin train",
                            "direct flights to berlin",
                            "london to berlin flight duration",
                            "best time to book flights to berlin"
                        ]
                    }
                ],
                "right": [
                    {
                        "type": "knowledge_graph",
                        "position": 1,
                        "url": "https:\/\/en.wikipedia.org\/wiki\/Bill_Gates",
                        "title": "Bill Gates",
                        "subtitle": "",
                        "description": "William Henry Gates III is an American business magnate, investor, author, philanthropist, humanitarian, and principal founder of Microsoft Corporation.",
                        "parts": [
                            "Bill GatesAmerican business magnate",
                            "gatesnotes.com",
                            "William Henry Gates III is an American business magnate, investor, author, philanthropist, humanitarian, and principal founder of Microsoft Corporation. Wikipedia",
                            "Born: October 28, 1955 (age 62 years), Seattle, WA",
                            "Net worth: 92.5 billion USD (2018) Forbes",
                            "Children: Jennifer Katharine Gates, Rory John Gates, Phoebe Adele Gates",
                            "Education: Harvard College (1973–1975), Lakeside School (1967–1973), Runcorn State High School, Harvard College",
                            "Did you know: Bill Gates has the highest amount given to charity ($35 billion) among the greatest philanthropists. wikipedia.org",
                            "QuotesYour most unhappy customers are your greatest source of learning.Success is a lousy teacher. It seduces smart people into thinking they can't lose.Life is not fair; get used to it.View 7+ moreView 7+",
                            "ProfilesTwitterFacebookInstagram",
                            "People also search forView 90+ moreView 90+Steve JobsJeff BezosMark ZuckerbergTim CookWarren Buffett"
                        ]
                    },
                    {
                        "type": "google_review",
                        "position": 2,
                        "reviews_count": 2657,
                        "place_id": "ChIJ6UCP2tygJ0ERRJmMWID1zMA"
                    }
                ]
            }
        }
    ]
}

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 array results array of tasks setting
      task_id integer unique task identifier in our system
you can use task_id to request task results any time within the next 30 days.
      post_id string index in the array received in a POST request
      se_id integer search engine id
      loc_id integer search engine location id
Location identifier that helps to find the needed location in our system.
      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_se_check_url string direct URL to search engine results
You can use it to make sure that we provide exact results
      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_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_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, top_stories, people_also_ask, local_pack, twitter, google_flights, jobs, answer_box, related_search, knowledge_graph
      result_serp_count integer total number of results in the SERP
      left array results array from the main body of the SERP with extra elements
here you can find the following elements: organic, paid, top_stories, people_also_ask, local_pack, carousel, images, video, map, twitter, app, shopping, google_flights, jobs, answer_box, related_search, related
            ‘paid’ element in SERP    
            type string type of element = ‘paid’
            position integer position in the SERP
            url string relevant URL of the Ad element
            title string snippet header of the Ad element
            snippet_row1 string first snippet row in the element
            snippet_row2 string second snippet row in the element
            links array links which are included to the SERP element snippet
                  url string relevant URL
                  title string snippet header
                  snippet string snippet
            stat array statistics
                  rating integer/float rating
the popularity rate based on reviews and displayed in the SERPs
                  rating_max integer maximum value for a rating
            ‘organic’ element in SERP    
            type string type of element = ‘organic’
            position integer position in the SERP
            featured_snippet boolean indicates whether the element is a featured_snippet
            image boolean indicates whether the element has an image
            video boolean indicates whether the element has a video
            url string relevant URL in the SERP
            title string snippet header in the SERP
            snippet string snippet in the SERP
            snippet_extra string additional snippet in the SERP
ratings, price, author, etc
            links array links which are included to the SERP element snippet
                  url string relevant URL
                  title string snippet header
                  snippet string snippet
            stat array statistics
                  rating integer/float rating
the popularity rate based on reviews and displayed in the SERPs
                  rating_max integer maximum value for a rating
            ‘featured snippet’ element in SERP    
            type string type of element = ‘featured_snippet’
            position integer position in the SERP
            url string relevant URL in the SERP
            title string snippet header in the SERP
            snippet string snippet in the SERP
            table array array of elements
                  table_header array array of table header strings
                  table_data array array of table row strings
            ‘top stories’ element in SERP    
            type string type of element = ‘top_stories’
            position integer position in the SERP
            items array array of items
                  url string relevant URL of the element
                  title string title of the element
            ‘answer box’ element in SERP    
            type string type of element = ‘answer_box’
            position integer position in the SERP
            text array array of the string with text elements
            links array array of URLs
                  url string relevant URL
                  anchor string anchor for the URL
            ‘people also ask’ element in SERP    
            type string type of element = ‘people_also_ask’
            position integer position in the SERP
            items array array of the string with text elements
            ‘app’ element in SERP    
            type string type of element = ‘app’
            position integer position in the SERP
            items array array of applications
                  url string relevant URL of the application
                  title string title of the application
                  snippet string snippet of the application
                  price string price for the application
            ‘carousel’ element in SERP    
            type string type of element = ‘carousel’
            position integer position in the SERP
            title string title of carousel
            items array array of items
                  title string title of the element
            ‘local pack’ element in SERP    
            type string type of element = ‘local_pack’
            position integer position in the SERP
            url string relevant URL of the element
            title string snippet header of the element
            snippet string snippet of the element
            rating integer/float rating
the popularity rate based on reviews and displayed in the SERPs
            rating_type string measurement units
shows which measurement units are used in the rating field
there are two possible options: stars, percents
            rating_max integer maximum value for a rating
            paid boolean paid advertisement
            ‘map’ element in SERP    
            type string type of element = ‘map’
            position integer position in the SERP
            url string relevant URL
            title string snippet header in the SERP
            ‘twitter’ element in SERP    
            type string type of element = ‘twitter’
            position integer position in the SERP
            url string URL of the twitter homepage
            title string title of the twitter
            items array array of items
                  url string URL of the tweet
                  tweet string tweet message
                  date string date of tweet message
            ‘shopping’ element in SERP    
            type string type of element = ‘shopping’
            position integer position in the SERP
            title string title of the product in google shopping
            items array array of items
                  title string title of the product
                  url string URL of the product
                  price string price of the product
                  source string source
            ‘video’ element in SERP    
            type string type of element = ‘video’
            position integer position in the SERP
            items array array of URL videos
                  url string URL of the video
                  title string title of the video
                  source string source of the video
            ‘images’ element in SERP    
            type string type of element = ‘images’
            position integer position in the SERP
            url string URL of the image
            title string title of the image
            position integer position in the SERP
            items array array of URL images
                  url string URL of the image
                  alt string alt attribute
            ‘google flights’ element in SERP    
            type string type of element = ‘google_flights’
            position integer position in the SERP
            url string URL of current tickets
            title string title
            position integer position in the SERP
            items array array of URLs
                  url string URL of this ticket
                  description string description
            ‘jobs’ element in SERP    
            type string type of element = ‘jobs’
            position integer position in the SERP
            url string URL of current jobs
            title string title
            position integer position in the SERP
            items array array of vacancies
                  url string URL of this vacancy
                  snippet string snippet
                  author string author
                  date string date of this vacancy
                  type string type of work
            ‘related search’ element in SERP    
            type string type of element = ‘related_search’
            position integer position in the SERP
            title string title of the related search element
            items array array of related keywords
            ‘related’ element in SERP    
            type string type of element = ‘related’
            position integer position in the SERP
            items array array of related keywords
      right array results array from the right side of the SERP with extra elements
here you can find the following elements: knowledge_graph
            ‘knowledge graph’ element in SERP    
            type string type of element = ‘knowledge_graph’
            position integer position in the SERP
            url string relevant URL in the SERP
            title string header in the SERP
            subtitle string subtitle in the SERP
            description string text of knowledge graph
            parts array array of knowledge graph text items
            ‘google_review’ element in SERP    
            type string type of element = ‘google_review’
            position integer position in the SERP
            reviews_count integer number of results in the reviews list
            place_id string place ID

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 Google Reviews 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();

$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_language" => "English",
    "loc_name_canonical"=> "London,England,United Kingdom",
    "se_deep" => 50,
    "sort_by" => "highest_rating",
    "key" =>  mb_convert_encoding("hedonism wines", "UTF-8")
);

$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_language" => "English",
    "loc_id" => 1006886,
    "se_deep" => 50,
    "sort_by" => "highest_rating",
    "key_id" => 30778900
);

if (count($post_array) > 0) {
    try {
        // POST /v2/srp_google_reviews_tasks_post/$data
        // $tasks_data must by array with key 'data'
        $task_post_result = $client->post('v2/srp_google_reviews_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[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_language="English",
    loc_name_canonical="London,England,United Kingdom",
    se_deep=50,
    sort_by="highest_rating",
    key="hedonism wines"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_language="English",
    loc_id=1006886,
    se_deep=50,
    sort_by="highest_rating",
    key_id=30778900
)

response = client.post("/v2/srp_google_reviews_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_google_reviews_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,
                    se_language = "English",
                    loc_name_canonical = "London,England,United Kingdom",
                    se_deep=50,
                    sort_by="highest_rating",
                    key = "hedonism wines"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_language = "English",
                    loc_id = 1006886,
                    se_deep=50,
                    sort_by="highest_rating",
                    key_id = 30778900
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/srp_google_reviews_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_google_reviews_tasks_post() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_google_reviews_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("se_language", "English");
        postObj1.put("loc_name_canonical", "London,England,United Kingdom");
        postObj1.put("se_deep", 50);
        postObj1.put("sort_by", "highest_rating");
        postObj1.put("key", "hedonism wines");
        postValues.put(rnd.nextInt(300000), postObj1);

        Map<String, Object> postObj2 = new HashMap<>();
        postObj2.put("priority", 1);
        postObj2.put("se_language", "English");
        postObj2.put("loc_id", 1006886);
        postObj2.put("se_deep", 50);
        postObj2.put("sort_by", "highest_rating");
        postObj2.put("key_id", 30778900);
        postValues.put(rnd.nextInt(30000000), postObj2);

        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": 2,
    "results": {
        "11913049": {
            "post_id": 11913049,
            "post_key": "hedonism wines",
            "task_id": 404227822,
            "loc_id": 1006886,
            "key_id": 30778900,
            "status": "ok"
        },
        "20469414": {
            "post_id": 20469414,
            "post_key": "hedonism wines",
            "task_id": 404227823,
            "loc_id": 1006886,
            "key_id": 30778900,
            "status": "ok"
        }
    }
}

All the data included in the POST request should be in the JSON format (UTF-8 encoding). The tasks shall be set through the POST method, by placing the tasks array into the data field. It is not recommended to set more than 100 tasks at once due to the different task variations you are likely to use. Note that the usage of the url field slows down the tasks processing. On the contrary, by using system identifiers (loc_id, key_id), you can accelerate the tasks processing and set more than 100 tasks at once.

You can get the completed task results via the unique task_id. Alternatively, you may indicate the pingback_url or postback_url to get task results send to a specific url.

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
se_language string language
required field
the list of available languages: “English”, “German”, “French”, “Spanish”, “Espanol (Latinoamerica)”, “Swedish”, “Norwegian”, “Danish”, “Dutch”, “Vietnamese”, “Portuguese (Portugal)”, “Chinese (Traditional)”, “Chinese (Simplified)”, “Russian”
default value: “English”
se_deep integer crawling depth
required field
specify the crawling depth
we strongly encourage setting a crawling depth in the multiples of ten, because our crawler processes ten reviews in a row
default value: 10
loc_id integer 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 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 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 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:’, ‘filetype:’, ‘id:’, ‘inanchor:’, ‘info:’, ‘intext:’, ‘intitle:’, ‘inurl:’, ‘link:’, ‘related:’, ‘site:’ then the charge per task will be multiplied by 10.
sort_by string type of sorting
optional field
search results filter type, you can specify:
newest - sort by newest first
highest_rating - sort by highest rating
lowest_rating - sort by lowest rating
relevant - sort by relevance
default value: relevant
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.

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 array results array of tasks setting
            task_id integer unique task identifier in our system
you can use task_id to request task results any time within the next 30 days.
            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)
            loc_id integer location id
if status=“ok”, then this field will be always filled
            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: location” - you’ve specified nonexistent loc_id or a location of a search engine wasn’t found by specified loc_name_canonical
404 “not found or not enough data: language” - you’ve specified nonexistent language
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 Google Reviews 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_google_reviews_tasks_get
    $tasks_get_result = $client->get('v2/srp_google_reviews_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_google_reviews_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_google_reviews_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_google_reviews_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_google_reviews_tasks_get() throws JSONException, URISyntaxException, IOException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_google_reviews_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": [
        {
            "post_id": 11577837,
            "post_key": "hedonism wines",
            "task_id": 25536431,
            "loc_id": 1006886,
            "key_id": 30778900,
            "result_se_check_url": "https://google.com/search?q=hedonism%20wines&hl=en&gl=US&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS",
            "results_count": 378
        }
    ]
}

You can get the list of completed tasks that have not been collected yet. Note that all collected results are automatically erased from the list.

By indicating the pingback_url or the postback_url you get the list of completed tasks to a specific url, avoiding the srp_google_reviews_tasks_get command. GET requests will be sent to the pingback_url, POST requests will be sent to the postback_url.

The list of completed results will be enclosed in the results field of the API response array.

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 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)
            loc_id integer location id
            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 reviews list
            result_se_check_url string direct URL to search engine results
You can use it to make sure that we provide exact results

Get Google Reviews 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_google_reviews_tasks_get
    $tasks_get_result = $client->get('v2/srp_google_reviews_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_google_reviews_tasks_get/$task_id
            $reviews_result = $client->get('v2/srp_google_reviews_tasks_get/'.$tasks_get_row["task_id"]);
            print_r($reviews_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_google_reviews_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_google_reviews_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_google_reviews_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_google_reviews_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_google_reviews_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_google_reviews_tasks_get_by_task_id() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/srp_extra_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_google_reviews_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.1376 sec.",
    "results_count": 100,
    "results": [
          {
              "task_id": 2467424648,
              "loc_id": 1006886,
              "key_id": 30778900,
              "post_id": 11577837,
              "post_key": "hedonism wines",
              "result_se_check_url": "https://google.com/search?q=hedonism%20wines&hl=en&gl=US&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS",
              "result_datetime": "2018-11-01 16:11:04 +00:00",
              "result_title": "Hedonism Wines",
              "result_sub_title": "3-7 Davies St, London, UK",
              "result_stat": {
                  "rating": 4.8,
                  "rating_max": 5
              },
              "result_reviews_count": 377,
              "result_place_id": "ChIJDxnC6SwFdkgRTYAlUwkFFU4",
              "result": [
                  {
                      "position": 1,
                      "review_text": "I would say this is a unique place in London for what it is. It's not only the shop you can buy pretty much any type of alcohol and get brilliant service from knowledgeable staff but also some sort of a creative place with always unique front displays and a very interesting owner, who you can meet there sometimes.Great Russian businessman who saw the potential, the need on the market and made this all a reality!I would advise anyone to come in and have a look for themselves, it's a true gem in the heart of London!",
                      "time_ago": "a month ago",
                      "stat": {
                          "rating": 5,
                          "rating_max": 5
                      },
                      "reviews_count": 19,
                      "photos_count": 11,
                      "local_guide": true,
                      "profile_name": "Cho Lujas",
                      "profile_url": null,
                      "profile_image_url": "https://lh5.googleusercontent.com/-ScIRqgD8ARM/AAAAAAAAAAI/AAAAAAAABD4/2WECAm1k4_o/s40-ba2-c0x00000000-cc-rp-mo/photo.jpg",
                      "owner_answer": null,
                      "owner_time_ago": null
                  },
                  {
                      "position": 2,
                      "review_text": "The best...what more can be said..wines from everywhere..israel...sardinia..oz..etc",
                      "time_ago": "4 days ago",
                      "stat": [],
                      "reviews_count": 1,
                      "photos_count": null,
                      "local_guide": false,
                      "profile_name": "A Google User",
                      "profile_url": null,
                      "profile_image_url": "https://lh3.googleusercontent.com/-veRGrSi7dcE/AAAAAAAAAAI/AAAAAAAAAAA/iRdrhnwCCLI/s40-c0x00000000-cc-rp-mo/photo.jpg",
                      "owner_answer": null,
                      "owner_time_ago": null
                  },
                  {
                      "position": 3,
                      "review_text": "Aparr from a great selection of wines, they have a self service wine counter in the basement. You can top up your card and enjoy on of the most interesting wines. Well done!",
                      "time_ago": "3 months ago",
                      "stat": {
                          "rating": 4,
                          "rating_max": 5
                      },
                      "reviews_count": 17,
                      "photos_count": 4,
                      "local_guide": true,
                      "profile_name": "Maria Kovalevskaya",
                      "profile_url": null,
                      "profile_image_url": "https://lh5.googleusercontent.com/-EnTNVhiiOmk/AAAAAAAAAAI/AAAAAAAABBE/0WHlT4cJtZ4/s40-ba2-c0x00000000-cc-rp-mo/photo.jpg",
                      "owner_answer": null,
                      "owner_time_ago": null
                  }
              ]
          }
    ]
}

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 result
results array results array of tasks setting
      task_id integer unique task identifier in our system
you can use task_id to request task results any time within the next 30 days.
      post_id string index in the array received in a POST request
      loc_id integer location id
Location identifier that helps to find the needed location in our system.
      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_se_check_url string direct URL to search engine results
You can use it to make sure that we provide exact results
      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_title string title in reviews list
      result_subtitle string subtitle in reviews list
      result_stat array ratings information about the reviews element of a result
empty array if result does not have a rating
            rating integer/float rating
the popularity rate based on reviews and displayed in the reviews list
            rating_max integer maximum value for a rating
      result_reviews_count integer total number of results in the reviews list
      result_place_id string place ID
      result array list of reviews
            position integer position in the reviews list
            review_text string text of the review
            time_ago string when the review was written and review’s source
            stat array ratings information about the reviews element of a result
empty array if result does not have a rating
                  rating integer/float rating
the popularity rate based on reviews and displayed in the reviews list
                  rating_max integer maximum value for a rating
            reviews_count integer number of reviews written by a user
            photos_count integer number of images posted by a user
            local_guide boolean if a user is “local guide”
            profile_name string name of the user who wrote a review
            profile_url string URL of profile of the user who wrote a review
            profile_image_url string URL of profile image of the user who wrote a review
            owner_answer string owner’s answer to a review
            owner_time_ago string when an answer was written

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” - reviews list is empty. Check if you have added key correctly
404 “top results not found” - there is no reviews list with specified parameters

Merchant API

The DataForSEO Merchant API provides is the most convenient way to get reliable e-commerce data about prices, products, and retailers. We have selected the most popular e-commerce platforms and would add even more in the nearest future. After you connect to Merchant API, you will be able to collect up-to-date information for analyzing competitors and making better business decisions.

Google Shopping

Google Shopping API provides TOP100 results at Google Shopping based on a keyword (product). Moreover, Google Shooping HTML service can provide you with the HTML page of SERP for any keyword. Using Google Shopping Shops you can get a list of shops by specifying product ID (the unique identifier of a product in Google Shopping).

The operating principle of Google Shopping API is similar to Rank Tracker API. The main difference is that with Google Shopping API you don’t recive all completed results at once. What you recive is a list of task_id of completed results, so each result should be requested separately using its task_id. This is due to huge amounts of data included in each Google Shopping API task.

You can find a list of available Google Shopping countries on this page.

Tasks with higher priority are processed faster. Therefore, the delivery of such results takes less time.

Setting Google Shopping 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/merchant_google_shopping_tasks_post' so you can use it.
    // The setting of a task can fail, if you set not-existent search engine, for example.
    $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=shoes&tbm=shop&tbs=vw:l&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 )
    // You must choose a search engine with the word "shopping" included into the "se_name" field
    // If a task was set successfully, this *_id will be returned in results: 'v2/merchant_google_shopping_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 shopping",
    "se_language" => "English",
    "loc_name_canonical"=> "London,England,United Kingdom",
    "key" =>  mb_convert_encoding("shoes", "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
    // You must choose a search engine with the word "shopping" included into the "se_name" field
    $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" => 2933,
    "loc_id" => 1006886,
    "key_id" => 68415
    );

    //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/merchant_google_shopping_tasks_post/$data
            // $tasks_data must by array with key 'data'
            $task_post_result = $client->post('v2/merchant_google_shopping_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/merchant_google_shopping_tasks_post/$data
        // $tasks_data must by array with key 'data'
        $task_post_result = $client->post('v2/merchant_google_shopping_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=shoes&tbm=shop&tbs=vw:l&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_name="google.co.uk shopping",
    se_language="English",
    loc_name_canonical="London,England,United Kingdom",
    key="shoes"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_id=2933,
    loc_id=1006886,
    key_id=68415
)

response = client.post("/v2/merchant_google_shopping_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 merchant_google_shopping_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=shoes&tbm=shop&tbs=vw:l&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_name = "google.co.uk shopping",
                    se_language = "English",
                    loc_name_canonical = "London,England,United Kingdom",
                    key = "shoes"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_id = 2933,
                    loc_id = 1006886,
                    key_id = 68415
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/merchant_google_shopping_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 merchant_google_shopping_tasks_post() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/merchant_google_shopping_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=shoes&tbm=shop&tbs=vw:l&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 shopping");
        postObj2.put("se_language", "English");
        postObj2.put("loc_name_canonical", "London,England,United Kingdom");
        postObj2.put("key", "shoes");
        postValues.put(rnd.nextInt(300000), postObj2);

        Map<String, Object> postObj3 = new HashMap<>();
        postObj3.put("priority", 1);
        postObj3.put("se_id", 2933);
        postObj3.put("loc_id", 1006886);
        postObj3.put("key_id", 68415);
        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": 3,
    "results": {
        "11913049": {
            "post_id": 11913049,
            "post_key": "shoes",
            "task_id": 404227822,
            "se_id": 2933,
            "loc_id": 1006886,
            "key_id": 68415,
            "status": "ok"
        },
        "20469414": {
            "post_id": 20469414,
            "post_key": "shoes",
            "task_id": 404227823,
            "se_id": 2933,
            "loc_id": 1006886,
            "key_id": 68415,
            "status": "ok"
        },
        "6273173": {
            "post_id": 6273173,
            "post_key": "shoes",
            "task_id": 404227824,
            "se_id": 2933,
            "loc_id": 1006886,
            "key_id": 68415,
            "status": "ok"
        }
    }
}

All the data included in the POST request should be in the JSON format (UTF-8 encoding). The tasks shall be set through the POST method, by placing the tasks array into the data field. It is not recommended to set more than 100 tasks at once due to the different task variations you are likely to use. Note that the usage of the url field slows down the tasks processing. On the contrary, by using system identifiers (se_id, lod_id, key_id), you can accelerate the tasks processing and set more than 100 tasks at once.

You can get the completed task results via the unique task_id. Alternatively, you may indicate the pingback_url or postback_url to get task results send to a specific URL.

Description of the fields for a task setting:

Name of a field Type Description
priority integer execution priority
optional field
can take the following 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, it will be sorted to the neccessary fields. Such method is more time-consuming and moreover it requires that you specify the exact language and location in the URL. We don’t recommend using this method.
example:
https://www.google.co.uk/search?q=shoes&tbm=shop&tbs=vw:l&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 availiable search engines with se_id can be accessed by sending a separate request to the List of Search Engines
to get se_id for Google Shopping you must choose a search engine with the word “shopping” included into the “se_name” field
also, you can find se_id in the array returned after the task setting is complete
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 availiable search engines with se_id can be accessed by sending a separate request to the List of Search Engines
you must specify a search engine where field “se_name” contains the word “shopping”
example: “google.co.uk shopping”
se_language string search engine language
required field if se_id is not specified
the list of available search engines with se_languages can be accessed by sending a separate request to the 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 avaliabale search engine locations with loc_id can be accessed by sending a separate request to the List of Locations
also, you can find loc_id in the array returned after the task setting is complete
please note that we use Google Geographical Targeting with the foolowing location types: 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 availiable search engine locations with loc_name_canonical can be accessed by sending a separate request to the List of Locations
please note that we use Google Geographical Targeting with the foolowing location types: 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”
price_min integer minimum search results price filter
optional field
minimum value: 0
price_max integer maximum search results price filter
optional field
price_orderby string sorting by prices
optional field
search results filter type can take two possible values:
abc - in ascending order
desc - in descending order
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, 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 Google Shopping 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 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 shopping","se_language":"English","loc_name_canonical":"London,England,United Kingdom","key":"shoes"}}}"
    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 shopping","se_language":"English","loc_name_canonical":"London,England,United Kingdom","key":"shoes"}}}"
    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”, you can see the more detailed information about the possible cause of an error in the error array
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
you can use task_id to request task results any time within the next 30 days.
            status string results of this task setting
“ok” - success
“error” - error
if status=“error”, you can see the more detailed information about the possible cause of an error in the error array
            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
Location identifier that helps to find the needed location in our system.
            loc_id integer search engine location id
if status=“ok”, then this field will be always filled
Location identifier that helps to find the needed location in our system.
            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: 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 Google Shopping 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/merchant_google_shopping_tasks_get
    $tasks_get_result = $client->get('v2/merchant_google_shopping_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/merchant_google_shopping_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 merchant_google_shopping_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/merchant_google_shopping_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 merchant_google_shopping_tasks_get() throws JSONException, URISyntaxException, IOException {
        URI url = new URI("https://api.dataforseo.com/v2/merchant_google_shopping_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": [
        {
            "post_id": "11577837",
            "post_key": "shoes",
            "task_id": 675785734,
            "se_id": 2933,
            "loc_id": 1006886,
            "key_id": 68415,
            "result_spell": "",
            "result_se_check_url": "https://www.google.co.uk/search?q=shoes&num=100&tbm=shop&&tbs=vw:l&hl=en&gl=GB&gws_rd=cr&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.

By indicating the pingback_url or the postback_url you get the list of completed tasks to a specific url, avoiding the extra merchant_google_shopping_tasks_get command. GET requests will be sent to the pingback_url, POST requests will be sent to the postback_url.

The list of completed results will be enclosed in the results field of the API response array.

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”, you can see the more detailed information about the possible cause of an error in the error array
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
you can use task_id to request task results any time within the next 30 days
            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
Location identifier that helps to find the needed location in our system.
            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_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 Google Shopping 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/merchant_google_shopping_tasks_get
    $tasks_get_result = $client->get('v2/merchant_google_shopping_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/merchant_google_shopping_tasks_get/$task_id
            $result = $client->get('v2/merchant_google_shopping_tasks_get/'.$tasks_get_row["task_id"]);
            print_r($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/merchant_google_shopping_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:
        ggl_srp_response = client.get("/v2/merchant_google_shopping_tasks_get/%d" % (result["task_id"]))
        if ggl_srp_response["status"] == "error":
            print("error. Code: %d Message: %s" % (ggl_srp_response["error"]["code"], ggl_srp_response["error"]["message"]))
        else:
            print(ggl_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 google_shopping_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/merchant_google_shopping_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 response = await httpClient.GetAsync($"v2/merchant_google_shopping_tasks_get/{completedTask.task_id}");
                    var obj = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
                    if (obj.status == "error")
                        Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
                    foreach (var shopResult in obj.results)
                        Console.WriteLine(((IEnumerable<dynamic>)shopResult).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 google_shopping_tasks_get_by_task_id() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/merchant_google_shopping_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 getShopSerp = new HttpGet("https://api.dataforseo.com/v2/merchant_google_shopping_tasks_get/" + results.getJSONObject(i).get("task_id"));
                System.out.println(results.getJSONObject(i).get("task_id"));
                getShopSerp.setHeader("Content-type", "application/json");
                getShopSerp.setHeader("Authorization", "Basic " + basicAuth);
                HttpResponse serpResponse = client.execute(getShopSerp);
                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": [
            {
                "task_id": 676669794,
                "post_id": "949845416541",
                "se_id": 2933,
                "loc_id": 1006886,
                "key_id": 68415,
                "post_key": "shoes",
                "result_position": 1,
                "result_datetime": "2018-05-29 14:41:29 +00:00",
                "result_title": "Stradivarius Slingback mid-heel Court Shoes Woman Mustard 4",
                "result_description": "Mustard 4 - polyester,polyester,polyurethane,polyurethane thermoplastic,",
                "result_product_id": null,                
                "result_price": 19.99,
                "result_currency": "GBP",
                "result_stars": null,
                "result_reviews_count": null,
                "result_shop_stat": null,
                "result_shop_stat_type": null,
                "result_shop_stat_count": null,
                "result_tags": [],
                "result_spell": null,
                "result_url": "https://www.stradivarius.com/gb/partnumbers-c1020132524p300516502.html?colorId=124&LGWCODE=1287734112437V2018;123611;7451",
                "result_shopping_url": null,
                "result_se_check_url": "https://www.google.co.uk/search?q=shoes&num=100&tbm=shop&&tbs=vw:l&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            },
            {
                "task_id": 676669794,
                "post_id": "949845416541",
                "se_id": 2933,
                "loc_id": 1006886,
                "key_id": 68415,
                "post_key": "shoes",
                "result_position": 2,
                "result_datetime": "2018-05-29 14:41:29 +00:00",
                "result_title": "Samuel Windsor Classic Oxford Shoe - Black",
                "result_description": "The Samuel Windsor commitment to quality ensures these handmade Classic black Oxford shoes will prove to be the finest - most ...",
                "result_product_id": null,
                "result_price": 45,
                "result_currency": "GBP",
                "result_stars": 4.62,
                "result_reviews_count": 1046,
                "result_shop_stat": 4.5,
                "result_shop_stat_type": "stars",
                "result_shop_stat_count": 9627,
                "result_tags": [],
                "result_spell": null,
                "result_url": "https://www.samuel-windsor.co.uk/buy.cfm/oxford-shoes/classic-oxford-shoe-black/73/yes/53960?Affiliate=12,400",
                "result_shopping_url": null,
                "result_se_check_url": "https://www.google.co.uk/search?q=shoes&num=100&tbm=shop&&tbs=vw:l&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            },



            {
                "task_id": 676669794,
                "post_id": "949845416541",
                "se_id": 2933,
                "loc_id": 1006886,
                "key_id": 68415,
                "post_key": "shoes",
                "result_position": 98,
                "result_datetime": "2018-05-29 14:41:29 +00:00",
                "result_title": "ASOS DESIGN Dare Chunky Trainers - White",
                "result_description": "Trainers by ASOS DESIGN, All-white, alright?, Lace-up fastening, Padded tongue and cuff, Chunky sole, Moulded tread. Giving ...",
                "result_product_id": null,
                "result_price": 38,
                "result_currency": "GBP",
                "result_stars": null,
                "result_reviews_count": null,
                "result_shop_stat": 4.4,
                "result_shop_stat_type": "stars",
                "result_shop_stat_count": 1013,
                "result_tags": [
                    "ASOS",
                    "Trainer",
                    "Women's"
                ],
                "result_spell": null,
                "result_url": "http://www.asos.com/asos/asos-design-dare-chunky-trainers/prd/9665793?&affid=14173&channelref=product+search&mk=abc&currencyid=1",
                "result_shopping_url": null,
                "result_se_check_url": "https://www.google.co.uk/search?q=shoes&num=100&tbm=shop&&tbs=vw:l&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            },
            {
                "task_id": 676669794,
                "post_id": "949845416541",
                "se_id": 2933,
                "loc_id": 1006886,
                "key_id": 68415,
                "post_key": "shoes",
                "result_position": 99,
                "result_datetime": "2018-05-29 14:41:29 +00:00",
                "result_title": "Nike Zoom Strike Men's Running Shoe - Grey",
                "result_description": "Light, simple and comfortable runner from Nike. Fitted with Zoom Air tech in the heel, for efficient and responsive cushioning ...",
                "result_product_id": "3198619856837288516",
                "result_price": 69.95,
                "result_currency": "GBP",
                "result_stars": 4,
                "result_reviews_count": 13,
                "result_shop_stat": null,
                "result_shop_stat_type": null,
                "result_shop_stat_count": null,
                "result_tags": [],
                "result_spell": null,
                "result_url": "https://www.nike.com/gb/t/zoom-strike-running-shoe-XPTbL94M/AJ0189-002",
                "result_shopping_url": "https://www.google.co.uk/shopping/product/3649279603778976255?q=shoes&num=100&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS&prds=paur:ClkAsKraX2Dv16zu-Np0yyKeV4JMTK8p4ssp7ibx0X28uNZMjj0wz0-pBBt7XkKXihkDCvJVNCEZwragNodVkRI4btZrtcK6IZICQH_oLopmsO7jKuJdncUllxIZAFPVH71fuI8Be62rZSA5r3VLtAUT_jdDvA&sa=X&ved=0ahUKEwiV14nVk6vbAhXBRhQKHUPbCakQwBMI1Q8",
                "result_se_check_url": "https://www.google.co.uk/search?q=shoes&num=100&tbm=shop&&tbs=vw:l&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            },
            {
                "task_id": 676669794,
                "post_id": "949845416541",
                "se_id": 2933,
                "loc_id": 1006886,
                "key_id": 68415,
                "post_key": "shoes",
                "result_position": 100,
                "result_datetime": "2018-05-29 14:41:29 +00:00",
                "result_title": "New Balance 247 Classic - Red/White (Size EU 42 / UK 8)",
                "result_description": "The 247 sneaker is designed to keep up with your demanding life on the move. Sneaker is lightweight and flexible with a ...",
                "result_product_id": null,
                "result_price": 45,
                "result_currency": "GBP",
                "result_stars": 4.18,
                "result_reviews_count": 11,
                "result_shop_stat": null,
                "result_shop_stat_type": null,
                "result_shop_stat_count": null,
                "result_tags": [],
                "result_spell": null,
                "result_url": "http://www.newbalance.co.uk/pd/247-Classic/190737388547.html?Ecid=ps_MRL247RW_Google_PLA&ncr=true&&CAWELAID=172000720000053417",
                "result_shopping_url": null,
                "result_se_check_url": "https://www.google.co.uk/search?q=shoes&num=100&tbm=shop&&tbs=vw:l&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            }
        ],
        "paid": [
            {
                "task_id": 676669794,
                "post_id": "949845416541",
                "se_id": 2933,
                "loc_id": 1006886,
                "key_id": 68415,
                "post_key": "shoes",
                "result_position": 1,
                "result_datetime": "2018-05-29 14:41:29 +00:00",
                "result_title": "Shoes from JustFab® | Your First Style from £9\u200e",
                "result_snippet": "New VIPs Get Their First Exclusive Shoes from Just £9 Today!",
                "result_location": "bottom",
                "result_spell": null,
                "result_url": "https://style.justfab.co.uk/",
                "result_se_check_url": "https://www.google.co.uk/search?q=shoes&num=100&tbm=shop&&tbs=vw:l&hl=en&gl=GB&gws_rd=cr&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
            }
        ],
        "extra": {
            "related": [
                [
                    "nike shoes",
                    "adidas shoes",
                    "jordan shoes",
                    "basketball shoes",
                    "light up shoes",
                    "gucci shoes",
                    "puma shoes"                
                ]
            ]
        }
    }
}

Description of the fields for a request setting:

Name of a field Type Description
task_id integer unique task identifier in our system
you can use task_id to request task results any time within the next 30 days

The list of completed results will be enclosed in the results field of the API response array.

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”, you can see the more detailed information about the possible cause of an error in the error array
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 setting
      organic array results array of organic Google Shopping SERP
            task_id integer unique task identifier in our system
you can use task_id to request task results any time within the next 30 days. 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
Location identifier that helps to find the needed location in our system.
            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 key received in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            result_position integer position in the Google Shopping 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_title string snippet header in the Google Shopping SERP
            result_description string product description
            result_product_id string product ID
the unique identifier of a product in Google Shopping
if there are no values, you will get null
            result_price float product price
            result_currency string currency type
in the ISO format
            result_stars float product rating
(represented by star symbols) from 0 to 5
if there are no values, you will get null
            result_reviews_count integer number of feedbacks
left by users for a certain product
if there are no values, you will get null
            result_shop_stat float/integer shop rating
based on data collected by Google and/or its partners
in the event that the measurement unit in the result_shop_stat_type is equal to stars, the value can be in the range 0 to 5
if the measurement unit is equal to percents, the value can be in the range 0 to 100
if there are no values, you will get null
            result_shop_stat_type string measurement units
shows which measurement units are used in the result_shop_stat field
there are two possible options: stars, percents
if there are no values, you will get null
            result_shop_stat_count integer number of shop feedbacks
left by users collected by Google and/or its partners
if there are no values, you will get null
            result_tags array tags specified within ads
if there is no data, the array will be empty
            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
if there are no values, you will get null
            result_url string a URL of shop where a specified product is being sold
            result_shopping_url string a URL to the product in the Google Shopping platform
if there are no values, you will get null
            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 Google Shopping SERP
            task_id integer unique task identifier in our system
you can use task_id to request task results any time within the next 30 days
            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
Location identifier that helps to find the needed location in our system.
            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 key received in a POST array
keyword is returned with decoded %## (plus symbol ‘+’ will be decoded to a space character)
            result_position integer position in the Google Shopping 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_title string snippet header in the Google Shopping SERP
            result_snippet string snippet in the Google Shopping SERP
            result_location string ad position
can have the following values: top, bottom
            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
if there are no values, you will get null
            result_url string relevant URL in the Google Shopping SERP
            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 Google Shopping SERP elements
            related array array of ‘related search queries’ strings
this array will be present if the element is in the Google Shopping 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” - Google Shopping SERP is empty. Check if you have added key correctly
404 “top results not found” - there is no Google Shopping SERP with specified parameters

Setting Google Shopping 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/merchant_google_shopping_html_tasks_post' so you can use it.
    // The setting of a task can fail, if you set not-existent search engine, for example.
    $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=shoes&tbm=shop&tbs=vw:l&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 )
    // You must choose a search engine with the word "shopping" included into the "se_name" field
    // If a task was set successfully, this *_id will be returned in results: 'v2/merchant_google_shopping_html_tasks_get' 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 shopping",
    "se_language" => "English",
    "loc_name_canonical"=> "London,England,United Kingdom",
    "key" =>  mb_convert_encoding("shoes", "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
    // You must choose a search engine with the word "shopping" included into the "se_name" field
    $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" => 2933,
    "loc_id" => 1006886,
    "key_id" => 68415
    );

    //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/merchant_google_shopping_tasks_post/$data
            // $tasks_data must by array with key 'data'
            $task_post_result = $client->post('v2/merchant_google_shopping_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/merchant_google_shopping_html_tasks_post/$data
        // $tasks_data must by array with key 'data'
        $task_post_result = $client->post('v2/merchant_google_shopping_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=shoes&tbm=shop&tbs=vw:l&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_name="google.co.uk shopping",
    se_language="English",
    loc_name_canonical="London,England,United Kingdom",
    key="shoes"
)
post_data[rnd.randint(1, 30000000)] = dict(
    priority=1,
    se_id=2933,
    loc_id=1006886,
    key_id=68415
)

response = client.post("/v2/merchant_google_shopping_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 merchant_google_shopping_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=shoes&tbm=shop&tbs=vw:l&hl=en&gl=GB&uule=w+CAIQIFISCXXeIa8LoNhHEZkq1d1aOpZS"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_name = "google.co.uk shopping",
                    se_language = "English",
                    loc_name_canonical = "London,England,United Kingdom",
                    key = "shoes"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    priority = 1,
                    se_id = 2933,
                    loc_id = 1006886,
                    key_id = 68415
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/merchant_google_shopping_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 merchant_google_shopping_html_tasks_post() throws IOException, JSONException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/merchant_google_shopping_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=shoes&tbm=shop&tbs=vw:l&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 shopping");
        postObj2.put("se_language", "English");
        postObj2.put("loc_name_canonical", "London,England,United Kingdom");
        postObj2.put("key", "shoes");
        postValues.put(rnd.nextInt(300000), postObj2);

        Map<String, Object> postObj3 = new HashMap<>();
        postObj3.put("priority", 1);
        postObj3.put("se_id", 2933);
        postObj3.put("loc_id", 1006886);
        postObj3.put("key_id", 68415);
        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": {
            "post_id": "19840083",
            "post_key": "shoes",
            "task_id": 681890700,
            "se_id": 2972,
            "loc_id": 2840,
            "key_id": 68415,
            "status": "ok"
        },
        "6273173": {
            "post_id": "19840083",
            "post_key": "shoes",
            "task_id": 681890700,
            "se_id": 2972,
            "loc_id": 2840,
            "key_id": 68415,
            "status": "ok"
        },
        "19840083": {
            "post_id": "19840083",
            "post_key": "shoes",
            "task_id": 681890700,
            "se_id": 2972,
            "loc_id": 2840,
            "key_id": 68415,
            "status": "ok"
        }
    }
}

All the data included in the POST request should be in the JSON format (UTF-8 encoding). The tasks shall be set through the POST method, by placing the tasks array into the data field. It is not recommended to set more than 100 tasks at once due to the different task variations you are likely to use. Note that the usage of the url field slows down the tasks processing. On the contrary, by using system identifiers (se_id, lod_id, key_id), you can accelerate the tasks processing and set more than 100 tasks at once.

You can get the completed task results via the unique task_id. Alternatively, you may indicate the pingback_url or postback_url to get task results send to a specific URL.

Description of the fields for a task setting:

Name of a field Type Description
priority integer execution priority
optional field
can take the following 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, it will be sorted to the neccessary fields. Such method is more time-consuming and moreover it requires that you specify the exact language and location in the URL. We don’t recommend using this method.
example:
https://www.google.co.uk/search?q=shoes&tbm=shop&tbs=vw:l&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 availiable search engines with <