NAV Navbar
Logo
php python csharp java

Keywords Data API

Google

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

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

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

Search Volume for Keyword

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

There are two methods to retrieve data: Live and Delayed

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

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

You can also check the update status of keywords search volume returned by Google API using Get AdWords Status.

Live Data

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

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

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

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


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

    //do something with results

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

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

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

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

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

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

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

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

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

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

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

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

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

The above command returns JSON structured like this:

{
    "status": "ok",
    "task_id": 423292503,
    "results_time": "2.1886 sec.",
    "results_count": 3,
    "results": [
        {
            "language": "en",
            "loc_id": 2840,
            "key": "leads and prospects",
            "cmp": 0.47619047619048,
            "cpc": 0,
            "sv": 10,
            "categories": [
                10019,
                10276,
                10885,
                11273,
                13418,
                11088,
                12209,
                10004,
                10102,
                10007,
                12376,
                10296,
                10168,
                10012
            ],
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 10
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "adsense blank ads how long",
            "cmp": 0,
            "cpc": 0,
            "sv": 10,
            "categories": [],
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 0
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 0
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 0
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "average page rpm adsense",
            "cmp": null,
            "cpc": null,
            "sv": null,
            "categories": [],
            "ms": null
        }
    ]
}

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

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

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

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

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

Possible errors codes:

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

Set Task

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

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

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

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

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

        //do something with post results

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

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

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

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),
                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    language = "en",
                    loc_name_canonical = "United States",
                    key = "average page rpm adsense"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    language = "en",
                    loc_id = 2840,
                    key = "adsense blank ads how long"
                },
                [rnd.Next(1, 30000000)] = new
                {
                    language = "en",
                    loc_name_canonical = "United States",
                    key = "leads and prospects"
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_sv_tasks_post", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            foreach (var result in obj.results)
            {
                Console.WriteLine(result);
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

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

Each array element has such structure:

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

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

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

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

Possible errors codes

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

Get Completed Tasks

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

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

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

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

    //get tasks one by one

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

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

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
response = client.get("/v2/kwrd_sv_tasks_get")
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using Newtonsoft.Json;
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;

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

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

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

The above command returns JSON structured like this:

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

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

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

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

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

Possible errors codes

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

Get Results by task_id

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

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

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

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

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

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

Possible errors codes

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

Bulk Keyword Search Volume

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

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

There are two methods to retrieve data: Live and Delayed

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

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

You can also check the update status of keywords search volume returned by Google API using Get AdWords Status.

Live Data

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

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

try {

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

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


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

    //do something with results

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

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

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

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


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

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

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

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

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

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

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

The above command returns JSON structured like this:

{
    "status": "ok",
    "task_id": 423292503,
    "results_time": "2.1886 sec.",
    "results_count": 3,
    "results": [
        {
            "language": "en",
            "loc_id": 2840,
            "key": "leads and prospects",
            "cmp": 0.47619047619048,
            "cpc": 0,
            "sv": 10,
            "categories": [
                10019,
                10276,
                10885,
                11273,
                13418,
                11088,
                12209,
                10004,
                10102,
                10007,
                12376,
                10296,
                10168,
                10012
            ],
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 10
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "adsense blank ads how long",
            "cmp": 0,
            "cpc": 0,
            "sv": 10,
            "categories": [],
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 0
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 0
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 0
                }
            ]
        },
        {
            "language": "en",
            "loc_id": 2840,
            "key": "average page rpm adsense",
            "cmp": null,
            "cpc": null,
            "sv": null,
            "categories": [],
            "ms": null
        }
    ]
}

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

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

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

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

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

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

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

Possible errors codes:

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

Set Task

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

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

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

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

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

        //do something with post results

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

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

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

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

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_sv_batch_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),
                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    language = "en",
                    loc_name_canonical = "United States",
                    keys = new[]
                    {
                        "repeat customers",
                        "best sleeping wireless earbuds",
                        "staniel cay day trip",
                        "iota hoodie",
                        "monero hat"
                    }
                }
            };

            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_sv_batch_tasks_post", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
            {
                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}");
                }
            }
            else
            {
                foreach (var result in obj.results)
                {
                   Console.WriteLine(result);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

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

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

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

Each array element has such structure:

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

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

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

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

Possible errors codes

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

Get Completed Tasks

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

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

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

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

    //get tasks one by one

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

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

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

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

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

Possible errors codes

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

Get Results by task_id

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

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

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

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

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

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

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

Possible errors codes

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

Keywords for Domain

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

There are two methods to retrieve data: Live and Delayed

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

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

You can also check the update status of keywords search volume returned by Google API using Get AdWords Status.

Live Data

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

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

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

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

    //do something with results

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

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

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

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

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

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

The above command returns JSON structured like this:

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


        {
            "language": "en",
            "loc_id": 2840,
            "key": "check serp ranking for keyword",
            "cmp": 0.097560975609756,
            "cpc": 0,
            "sv": 10,
            "categories": [
                13152,
                10019,
                13316,
                10276,
                10885,
                11497,
                13418,
                11498,
                12204,
                11088,
                10004,
                10007,
                12376,
                10168
            ],
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 40
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 50
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 20
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 20
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 10
                }
            ]
        }
    ]
}

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

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

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

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

Possible errors codes:

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

Set Task

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

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

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

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

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

        //do something with post results

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

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

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

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

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

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

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

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

Each array element has such structure:

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

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

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

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

Possible errors codes

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

Get Completed Tasks

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

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

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

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

    //get tasks one by one

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

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

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

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

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

Possible errors codes

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

Get Results by task_id

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

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

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

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

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

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

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

Possible errors codes

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

Keywords for Keywords

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

There are two methods to retrieve data: Live and Delayed

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

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

You can also check the update status of keywords search volume returned by Google API using Get AdWords Status.

Live Data

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

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

try {

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

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

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

    //do something with results

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

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

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

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

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_keywords()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),
                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };

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

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

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

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

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

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

The above command returns JSON structured like this:

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


        {
            "language": "en",
            "loc_id": 2840,
            "key": "check serp ranking for keyword",
            "cmp": 0.097560975609756,
            "cpc": 0,
            "sv": 10,
            "categories": [
                13152,
                10019,
                13316,
                10276,
                10885,
                11497,
                13418,
                11498,
                12204,
                11088,
                10004,
                10007,
                12376,
                10168
            ],
            "ms": [
                {
                    "year": 2016,
                    "month": 10,
                    "count": 40
                },
                {
                    "year": 2016,
                    "month": 9,
                    "count": 50
                },
                {
                    "year": 2016,
                    "month": 8,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 7,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 6,
                    "count": 0
                },
                {
                    "year": 2016,
                    "month": 5,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 4,
                    "count": 20
                },
                {
                    "year": 2016,
                    "month": 3,
                    "count": 20
                },
                {
                    "year": 2016,
                    "month": 2,
                    "count": 10
                },
                {
                    "year": 2016,
                    "month": 1,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 12,
                    "count": 10
                },
                {
                    "year": 2015,
                    "month": 11,
                    "count": 10
                }
            ]
        }
    ]
}

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

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

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

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

Possible errors codes:

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

Set Task

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

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

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

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

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

        //do something with post results

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

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

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

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

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

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

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

Each array element has such structure:

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

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

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

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

Possible errors codes

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

Get Completed Tasks

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

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

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

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

    //get tasks one by one

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

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

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

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

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

public class Demos {
    public static void kwrd_for_keywords_tasks_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_keywords_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.0974 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 219463,
            "post_id": "your post_id parameter here",
            "status": "ok"
        }
    ]
}

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

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

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

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

Possible errors codes

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

Get Results by task_id

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

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

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

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

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

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

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

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

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

public class Demos {
    public static void kwrd_for_keywords_tasks_get_by_task_id() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_keywords_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++) {
                String taskId = results.getJSONObject(i).get("task_id").toString();
                HttpGet getKwrd = new HttpGet("https://api.dataforseo.com/v2/kwrd_for_keywords_tasks_get/" + taskId);
                System.out.println(taskId);
                getKwrd.setHeader("Content-type", "application/json");
                getKwrd.setHeader("Authorization", "Basic " + basicAuth);
                HttpResponse serpResponse = client.execute(getKwrd);
                JSONObject kwrdObj = new JSONObject(EntityUtils.toString(serpResponse.getEntity()));
                if (kwrdObj.get("status").equals("error")) {
                    System.out.println("error. Code:" + kwrdObj.getJSONObject("error").get("code") + " Message: " + kwrdObj.getJSONObject("error").get("message"));
                } else {
                    System.out.println(kwrdObj.toString());
                }
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0985 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 219463,
            "post_id": "your post_id parameter here",
            "status": "ok",
            "result": [
                {
                    "language": "en",
                    "loc_id": 2840,
                    "key": "serp",
                    "cmp": 0.007817985417229273,
                    "cpc": 3.044352,
                    "sv": 12100,
                    "categories": [
                        13152,
                        11088,
                        13316,
                        10276,
                        10004,
                        10007,
                        12376,
                        13418
                    ],
                    "ms": [
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 9900
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 12100
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 12100
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 9900
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 12100
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 12100
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 9900
                        },
                        {
                            "year": 2017,
                            "month": 5,
                            "count": 12100
                        },
                        {
                            "year": 2017,
                            "month": 4,
                            "count": 12100
                        },
                        {
                            "year": 2017,
                            "month": 3,
                            "count": 12100
                        },
                        {
                            "year": 2017,
                            "month": 2,
                            "count": 12100
                        },
                        {
                            "year": 2017,
                            "month": 1,
                            "count": 12100
                        }
                    ]
                },
                {
                    "language": "en",
                    "loc_id": 2840,
                    "key": "best seo",
                    "cmp": 0.18683419830647363,
                    "cpc": 7.467613,
                    "sv": 880,
                    "categories": [
                        13152,
                        11088,
                        13316,
                        10276,
                        10004,
                        10007,
                        12376,
                        13418
                    ],
                    "ms": [
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 1000
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 480
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 1000
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 1000
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 880
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 880
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 590
                        },
                        {
                            "year": 2017,
                            "month": 5,
                            "count": 880
                        },
                        {
                            "year": 2017,
                            "month": 4,
                            "count": 720
                        },
                        {
                            "year": 2017,
                            "month": 3,
                            "count": 1000
                        },
                        {
                            "year": 2017,
                            "month": 2,
                            "count": 1000
                        },
                        {
                            "year": 2017,
                            "month": 1,
                            "count": 880
                        }
                    ]
                }  
            ]
        }
    ]
}

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

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

Possible errors codes

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

Keywords for Category

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

There are two methods to retrieve data: Live and Delayed

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

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

You can also check the update status of keywords search volume returned by Google API using Get AdWords Status.

Live Data

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

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

try {

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

    //You can download the list of categories by: https://developers.google.com/adwords/api/docs/appendix/productsservices.csv
    $post_array[] = array(
    "language" => "en",
    "loc_name_canonical"=> "United States",
    "category_id" => 13895
    );

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

    //do something with results

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

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

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

#You can download the list of categories by: https://developers.google.com/adwords/api/docs/appendix/productsservices.csv
keywords_list = [
    dict(
        language="en",
        loc_name_canonical="United States",
        category_id=13895
    )
]
response = client.post("/v2/kwrd_for_category", dict(data=keywords_list))
if response["status"] == "error":
    print("error. Code: %d Message: %s" % (response["error"]["code"], response["error"]["message"]))
else:
    print(response["results"])
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_category()
        {
            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"))) }
            };

            //You can download the list of categories by: https://developers.google.com/adwords/api/docs/appendix/productsservices.csv
            var postArray = new object[]
            {
                new { language = "en", loc_name_canonical = "United States", category_id = 13895 }
            };
            var response = await httpClient.PostAsync("v2/kwrd_for_category", new StringContent(JsonConvert.SerializeObject(new { data = postArray })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
            if (obj.status == "error")
                Console.WriteLine($"error. Code: {obj.error.code} Message: {obj.error.message}");
            else
            {
                foreach (var result in obj.results)
                    Console.WriteLine(result);
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

public class Demos {
    public static void kwrd_for_category() throws URISyntaxException, IOException, JSONException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_category");
        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<>();

        //You can download the list of categories by: https://developers.google.com/adwords/api/docs/appendix/productsservices.csv
        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("language", "en");
        postObj.put("loc_name_canonical", "United States");
        postObj.put("category_id", 13895);
        postValues.put(rnd.nextInt(30000000), postObj);

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

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

The above command returns JSON structured like this:

{
    "status": "ok",
    "task_id": 40356871,
    "results_time": "7.7805 sec.",
    "results_count": 700,
    "results": [
        {
            "loc_id": 2840,
            "language": "en",
            "key": "polygon",
            "cmp": 0.0023641022857323795,
            "cpc": 0.76973,
            "sv": 201000,
            "categories": [
                10273,
                10019,
                10885,
                13605,
                13895,
                11368,
                10121,
                11915,
                13388,
                13615,
                10004,
                10645,
                10168,
                10013,
                10014
            ],
            "ms": [
                {
                    "year": 2018,
                    "month": 5,
                    "count": 246000
                },
                {
                    "year": 2018,
                    "month": 4,
                    "count": 301000
                },
                {
                    "year": 2018,
                    "month": 3,
                    "count": 246000
                },
                {
                    "year": 2018,
                    "month": 2,
                    "count": 201000
                },
                {
                    "year": 2018,
                    "month": 1,
                    "count": 201000
                },
                {
                    "year": 2017,
                    "month": 12,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 11,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 10,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 9,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 8,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 7,
                    "count": 110000
                },
                {
                    "year": 2017,
                    "month": 6,
                    "count": 165000
                }
            ]
        },
        {
            "loc_id": 2840,
            "language": "en",
            "key": "norco",
            "cmp": 0.013728871081630123,
            "cpc": 1.27937,
            "sv": 165000,
            "categories": [
                11744,
                13605,
                10085,
                12902,
                13895,
                10121,
                10089,
                11915,
                13615,
                10645,
                10486,
                10011,
                11773,
                10014
            ],
            "ms": [
                {
                    "year": 2018,
                    "month": 5,
                    "count": 165000
                },
                {
                    "year": 2018,
                    "month": 4,
                    "count": 165000
                },
                {
                    "year": 2018,
                    "month": 3,
                    "count": 165000
                },
                {
                    "year": 2018,
                    "month": 2,
                    "count": 165000
                },
                {
                    "year": 2018,
                    "month": 1,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 12,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 11,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 10,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 9,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 8,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 7,
                    "count": 165000
                },
                {
                    "year": 2017,
                    "month": 6,
                    "count": 165000
                }
            ]
        },


        {
            "loc_id": 2840,
            "language": "en",
            "key": "murwood",
            "cmp": 0.0066137566137566125,
            "cpc": 0,
            "sv": 210,
            "categories": [
                10645,
                13605,
                13895,
                10121,
                11915,
                10014,
                13615
            ],
            "ms": [
                {
                    "year": 2018,
                    "month": 5,
                    "count": 210
                },
                {
                    "year": 2018,
                    "month": 4,
                    "count": 140
                },
                {
                    "year": 2018,
                    "month": 3,
                    "count": 210
                },
                {
                    "year": 2018,
                    "month": 2,
                    "count": 170
                },
                {
                    "year": 2018,
                    "month": 1,
                    "count": 210
                },
                {
                    "year": 2017,
                    "month": 12,
                    "count": 170
                },
                {
                    "year": 2017,
                    "month": 11,
                    "count": 170
                },
                {
                    "year": 2017,
                    "month": 10,
                    "count": 170
                },
                {
                    "year": 2017,
                    "month": 9,
                    "count": 260
                },
                {
                    "year": 2017,
                    "month": 8,
                    "count": 260
                },
                {
                    "year": 2017,
                    "month": 7,
                    "count": 170
                },
                {
                    "year": 2017,
                    "month": 6,
                    "count": 210
                }
            ]
        }
    ]
}

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

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

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

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

Possible errors codes:

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

Set Task

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

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

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

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

if (count($post_array) > 0) {
    try {
        $task_post_result = $client->post('/v2/kwrd_for_category_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")

#You can download the list of categories by: https://developers.google.com/adwords/api/docs/appendix/productsservices.csv
rnd = Random() #you can set as "index of post_data" your ID, string, etc. we will return it with all results.
post_data = dict()
post_data[rnd.randint(1, 30000000)] = dict(    
    language="en",
    loc_name_canonical="United States",
    category_id=13895
)

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

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_for_category_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"))) }
            };
            //You can download the list of categories by: https://developers.google.com/adwords/api/docs/appendix/productsservices.csv
            var rnd = new Random(); //you can set as "index of post_data" your ID, string, etc. we will return it with all results.
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new {
                    language = "en",
                    loc_name_canonical = "United States",
                    category_id = 13895
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_for_category_tasks_post", new StringContent(JsonConvert.SerializeObject(new {data = postObject})));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            if (obj.status == "error")
            {
                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}");
                }
            }
            else
            {
                foreach (var result in obj.results)
                {
                    Console.WriteLine(result);
                }
            }
        }
    }
}
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;

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

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

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

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

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

The above command returns JSON structured like this:

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

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

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

Each array element has such structure:

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

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

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

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

Possible errors codes

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

Get Completed Tasks

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

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

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

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

    //get tasks one by one

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

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

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

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

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

public class Demos {
    public static void kwrd_for_category_tasks_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_category_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.0974 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 219463558,
            "post_id": "your post_id parameter here",
            "status": "ok"
        }
    ]
}

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

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

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

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

Possible errors codes

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

Get Results by task_id

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

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

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

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

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

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

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

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

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

public class Demos {
    public static void kwrd_for_category_tasks_get_by_task_id() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_for_category_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++) {
                String taskId = results.getJSONObject(i).get("task_id").toString();
                HttpGet getKwrd = new HttpGet("https://api.dataforseo.com/v2/kwrd_for_category_tasks_get/" + taskId);
                System.out.println(taskId);
                getKwrd.setHeader("Content-type", "application/json");
                getKwrd.setHeader("Authorization", "Basic " + basicAuth);
                HttpResponse serpResponse = client.execute(getKwrd);
                JSONObject kwrdObj = new JSONObject(EntityUtils.toString(serpResponse.getEntity()));
                if (kwrdObj.get("status").equals("error")) {
                    System.out.println("error. Code:" + kwrdObj.getJSONObject("error").get("code") + " Message: " + kwrdObj.getJSONObject("error").get("message"));
                } else {
                    System.out.println(kwrdObj.toString());
                }
            }
        } else {
            System.out.println("no results");
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0395 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 40389413,
            "post_id": 49491179,
            "status": "ok",
            "result": [
                {
                    "loc_id": 2840,
                    "language": "en",
                    "key": "polygon",
                    "cmp": 0.0023641022857323795,
                    "cpc": 0.76973,
                    "sv": 201000,
                    "categories": [
                        10273,
                        10019,
                        10885,
                        13605,
                        13895,
                        11368,
                        10121,
                        11915,
                        13388,
                        13615,
                        10004,
                        10645,
                        10168,
                        10013,
                        10014
                    ],
                    "ms": [
                        {
                            "year": 2018,
                            "month": 5,
                            "count": 246000
                        },
                        {
                            "year": 2018,
                            "month": 4,
                            "count": 301000
                        },
                        {
                            "year": 2018,
                            "month": 3,
                            "count": 246000
                        },
                        {
                            "year": 2018,
                            "month": 2,
                            "count": 201000
                        },
                        {
                            "year": 2018,
                            "month": 1,
                            "count": 201000
                        },
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 110000
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 165000
                        }
                    ]
                },
                {
                    "loc_id": 2840,
                    "language": "en",
                    "key": "norco",
                    "cmp": 0.013728871081630123,
                    "cpc": 1.27937,
                    "sv": 165000,
                    "categories": [
                        11744,
                        13605,
                        10085,
                        12902,
                        13895,
                        10121,
                        10089,
                        11915,
                        13615,
                        10645,
                        10486,
                        10011,
                        11773,
                        10014
                    ],
                    "ms": [
                        {
                            "year": 2018,
                            "month": 5,
                            "count": 165000
                        },
                        {
                            "year": 2018,
                            "month": 4,
                            "count": 165000
                        },
                        {
                            "year": 2018,
                            "month": 3,
                            "count": 165000
                        },
                        {
                            "year": 2018,
                            "month": 2,
                            "count": 165000
                        },
                        {
                            "year": 2018,
                            "month": 1,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 165000
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 165000
                        }
                    ]
                },
                {
                    "loc_id": 2840,
                    "language": "en",
                    "key": "murwood",
                    "cmp": 0.0066137566137566125,
                    "cpc": 0,
                    "sv": 210,
                    "categories": [
                        10645,
                        13605,
                        13895,
                        10121,
                        11915,
                        10014,
                        13615
                    ],
                    "ms": [
                        {
                            "year": 2018,
                            "month": 5,
                            "count": 210
                        },
                        {
                            "year": 2018,
                            "month": 4,
                            "count": 140
                        },
                        {
                            "year": 2018,
                            "month": 3,
                            "count": 210
                        },
                        {
                            "year": 2018,
                            "month": 2,
                            "count": 170
                        },
                        {
                            "year": 2018,
                            "month": 1,
                            "count": 210
                        },
                        {
                            "year": 2017,
                            "month": 12,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 11,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 10,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 9,
                            "count": 260
                        },
                        {
                            "year": 2017,
                            "month": 8,
                            "count": 260
                        },
                        {
                            "year": 2017,
                            "month": 7,
                            "count": 170
                        },
                        {
                            "year": 2017,
                            "month": 6,
                            "count": 210
                        }
                    ]
                }
            ]
        }
    ]
}

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

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

Possible errors codes

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

Ads Traffic for Keywords

You can receive the set of stats for daily impressions, CPC and clicks estimation. It can be really useful to get this data to estimate real demand for a specific keyword, as it is much more accurate than regular search volume information, which shows the broad match estimation for group of similar keywords.

There are two methods to retrieve data: Live and Delayed

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

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

You can also check the update status of keywords search volume returned by Google API using Get AdWords Status.

Live Data

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

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

try {

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

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

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

    //do something with results

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

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

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

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

namespace DataForSeoDemos
{
    public static partial class Demos
    {
        public static async Task kwrd_ad_traffic_by_keywords()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),
                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };

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

public class Demos {
    public static void kwrd_ad_traffic_by_keywords() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_ad_traffic_by_keywords");
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));
        List<Map<String, Object>> postValues = new ArrayList<>();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("language", "en");
        postObj.put("loc_name_canonical", "United States");
        postObj.put("bid", (float) 100.0);
        postObj.put("match", "exact");
        postObj.put("keys", new String[]{"seo marketing"});
        postValues.add(postObj);

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

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

The above command returns JSON structured like this:

{
    "status": "ok",
    "task_id": 466312280,
    "results_time": "6.9194 sec.",
    "results_count": 1,
    "results": [
        {
            "seo marketing": {
                "language": "en",
                "loc_id": 2840,
                "bid": 100,
                "key": "seo marketing",
                "match": "exact",
                "ad_position_min": 1.11,
                "ad_position_max": 1,
                "ad_position_average": 1.06,
                "cpc_min": 13.46,
                "cpc_max": 16.45,
                "cpc_average": 14.95,
                "daily_impressions_min": 304.23,
                "daily_impressions_max": 371.84,
                "daily_impressions_average": 338.03,
                "daily_clicks_min": 4.59,
                "daily_clicks_max": 5.61,
                "daily_clicks_average": 5.1,
                "daily_cost_min": 67.61,
                "daily_cost_max": 82.64,
                "daily_cost_average": 75.12
            }
        }
    ]
}

You will get information for every single keyword in an array.

You can send up to 2500 keywords in one keys array. Our system will charge credits per request, no matter what the number of keywords in array is, the price for 1 or 2500 keywords will be the same.

All POST data should be sent in the JSON format (UTF-8 encoding). The keywords are sent by POST method passing tasks array. The data should be specified in the data field of this POST array. Each array element has such structure:

Name of a field Type Description
keys array array of keywords
required field
maximum 2500 keywords can be specified
each keyword should contain maximum 80 characters, each keyword phrase should contain maximum ten words
bid float maximum custom bid
required field
you must specify a bid. the collected data will be based on the value
match string match type for keywords
required field
can have the following values: “exact”, “broad”, “phrase”
loc_id integer search engine location id
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of available locations for search engines loc_id you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_id appropriate Criteria ID
Please note ‘Postal Code’ is not supported in Keywords Data API.
loc_name_canonical string full name of a location for search engine
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of the available locations with specifying of their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_name_canonical appropriate Canonical Name
for instance: “London,England,United Kingdom”
Please note ‘Postal Code’ is not supported in Keywords Data API.
language string language
optional field
can have the following values: “ar”, “bn”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “te”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
keys_negative array array of negative keywords
optional field
These keywords will be ignored in the results array
you can specify negative keywords in this field(maximum 200 keywords)

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

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you will be able to see more detailed information about array error error
error array informational array of error
only if status=“error”
the list of possible errors can be found below.
      code integer error code
      message string text description of an error
task_id integer unique task identifier in our system(UInt64)
results_time string execution time, seconds
results_count integer number of elements in the array of results results
results array array of results
      language string language
      loc_id integer search engine location id
      bid float maximum custom bid
      key string keyword
      match string match type for keywords
      ad_position_min float minimum ads position
represents the minimum advertising position
if there is no data then the value is null
      ad_position_max float maximum ads position
represents the maximum advertising position
if there is no data then the value is null
      ad_position_average float average ads position
represents the average advertising position
if there is no data then the value is null
      cpc_min float minimum value of cost-per-click
represents the minimum cost per click (USD) historically paid for the keyword
if there is no data then the value is null
      cpc_max float maximum value of cost-per-click
represents the maximum cost per click (USD) historically paid for the keyword
if there is no data then the value is null
      cpc_average float average value of cost-per-click
represents the average cost per click (USD) historically paid for the keyword
if there is no data then the value is null
      daily_impressions_min float minimum value of daily impressions
represents the minimum number of advertising daily impression
if there is no data then the value is null
      daily_impressions_max float maximum value of daily impressions
represents the maximum number of advertising daily impressions
if there is no data then the value is null
      daily_impressions_average float average value of daily impressions
represents the average number of advertising daily impressions
if there is no data then the value is null
      daily_clicks_min float minimum value of daily clicks
represents the minimum number of advertising daily clicks
if there is no data then the value is null
      daily_clicks_max float maximum value of daily clicks
represents the maximum number of advertising daily clicks
if there is no data then the value is null
      daily_clicks_average float average value of daily clicks
represents the average number of advertising daily clicks
if there is no data then the value is null
      daily_cost_min float minimum value of daily charge
represents the minimum advertising daily charge
if there is no data then the value is null
      daily_cost_max float maximum value of daily charge
represents the maximum advertising daily charge
if there is no data then the value is null
      daily_cost_average float average value of daily charge
represents the average advertising daily charge
if there is no data then the value is null

Possible errors codes:

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

Set Task

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

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

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

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

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

        //do something with post results

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

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

#Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
client = RestClient("login", "password")
rnd = Random() #you can set as "index of post_data" your ID, string, etc. we will return it with all results.
post_data = dict()
post_data[rnd.randint(1, 30000000)] = dict(    
    se_name="google.co.uk",
    se_language="English",
    loc_name_canonical="London,England,United Kingdom",
    bid = 999.0,
    match = "exact",
    keys=[
        "online rank checker",
        "best seo"
    ]
)

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

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

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

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

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

        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("language", "en");
        postObj.put("loc_name_canonical", "United States");
        postObj.put("bid", 999.0);
        postObj.put("match", "exact");
        postObj.put("keys", new String[]{"online rank checker", "best seo"});
        postValues.put(rnd.nextInt(30000000), postObj);
        JSONObject json = new JSONObject().put("data", postValues);
        StringEntity input = new StringEntity(json.toString());

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

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

The above command returns JSON structured like this:

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

You can send up to 2500 keywords in one keys array. Our system will charge credits per request, no matter what the number of keywords in array is, the price for 1 or 2500 keywords will be the same.

You will get information for every single keyword in an array.

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

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

Each array element has such structure:

Name of a field Type Description
keys array array of keywords
required field
maximum 2500 keywords can be specified
each keyword should contain maximum 80 characters, each keyword phrase should contain maximum ten words
bid float maximum custom bid
required field
you must specify a bid. the collected data will be based on the value
match string match type for keywords
required field
can have the following values: “exact”, “broad”, “phrase”
loc_id integer search engine location id
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of available locations for search engines loc_id you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_id appropriate Criteria ID
Please note ‘Postal Code’ is not supported in Keywords Data API.
loc_name_canonical string full name of a location for search engine
optional field
you must choose one of the fields loc_id or loc_name_canonical
if you want to get results for international search, the field loc_id or loc_name_canonical should be empty
list of the available locations with specifying of their loc_name_canonical you can receive by separate request List of Locations
please notice that we use Google Geographical Targeting, that’s why you are able to point in the field loc_name_canonical appropriate Canonical Name
for instance: “London,England,United Kingdom”
Please note ‘Postal Code’ is not supported in Keywords Data API.
language string language
optional field
can have the following values: “ar”, “bn”, “bg”, “ca”, “zh_cn”, “zh_tw”, “hr”, “cs”, “da”, “nl”, “en”, “et”, “tl”, “fi”, “fr”, “de”, “el”, “iw”, “hi”, “hu”, “is”, “id”, “it”, “ja”, “ko”, “lv”, “lt”, “ms”, “no”, “fa”, “pl”, “pt”, “ro”, “ru”, “sr”, “sk”, “sl”, “es”, “sv”, “te”, “th”, “tr”, “uk”, “ur”, “vi”
Source Google AdWords API - Languages available for targeting
keys_negative array array of negative keywords
optional field
These keywords will be ignored in the results array
you can specify negative keywords in this field(maximum 200 keywords)
postback_url string return URL for sending task results
optional field
if you specify this URL there will be no need to pick up tasks using Get Rank Tasks Results. We will send a result of a completed task by POST request for URL as soon as a task is completed.
pingback_url string notification URL of a completed task
optional field
when a task is completed we will notify you by GET request sent to the URL you have specified
you can use string ‘$task_id’ as $task_id variable and ‘$post_id’ as $post_id variable. we will set necessary values before sending of a request. for example:
  http://your-server.com/pingscript?taskId=$task_id
  http://your-server.com/pingscript?taskId=$task_id&postId=$post_id

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

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

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

Possible errors codes

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

Get Completed Tasks

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

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

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

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

    //get tasks one by one

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

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

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

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

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

public class Demos {
    public static void kwrd_ad_traffic_by_keywords_tasks_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_ad_traffic_by_keywords_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 kwrdAdTrafficByKeywordsResponse = client.execute(get);
        JSONObject kwrdAdTrafficByKeywordsObj = new JSONObject(EntityUtils.toString(kwrdAdTrafficByKeywordsResponse.getEntity()));

        if (kwrdAdTrafficByKeywordsObj.get("status") == "error") {
            JSONObject errorObj = kwrdAdTrafficByKeywordsObj.getJSONObject("error");
            System.out.println("error. Code: " + errorObj.get("code") + " Message: " + errorObj.get("message"));
        } else if (!kwrdAdTrafficByKeywordsObj.get("results_count").equals(0)) {
            JSONArray results = kwrdAdTrafficByKeywordsObj.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.0795 sec.",
    "results_count": 1,
    "results": [
        {
            "task_id": 219737,
            "post_id": "your post_id parameter here",
            "status": "ok"
        }
    ]
}

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

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

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

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

Possible errors codes

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

Get Results by task_id

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

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

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

    // #1 - get task_id list of ALL ready results
    //GET /v2/kwrd_ad_traffic_by_keywords_tasks_get
    $tasks_get_result = $client->