NAV Navbar
Logo
php python csharp java

Keywords Finder API

One of the most important parts of a website optimization is the creation of keyword list. It is significant both for SEO and Ads. Using Keyword Finder API, you will be able to create or improve a list of keywords relevant to your project. Also, you can understand for what keywords your or rival’s website is ranked.

We use in-house keyword database. Actual keywords and SERP volumes of our database can be found on the Home Page Keywords Finder API page. The base is being continuously increased and soon other locations and languages will be available.

Using this method, you will get keywords that are related to a keyword you are going to provide. Also, you can receive the average search volume, 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. Related keywords are provided by Google in the SERP based on a search query. Eight keywords can be found at the end of a search engine results page. Also, there is a possibility to get related terms for related keywords, if you specify the depth of related search in the depth field.

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();
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "keyword" => "mountain house",
        "country_code" => "US",
        "language" => "en",
        "depth" => 2,
        "limit" => 1,
        "offset" => 0,
        "orderby" => "cpc,desc",
        "filters" => array(
            array("cpc", ">", 0),
            "or",
            array(
                array("search_volume", ">", 0),
                "and",
                array("search_volume", "<=", 1000)
            )
        )
    );

    $get_result = $client->post("v2/kwrd_finder_related_keywords_get", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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(
    keyword="mountain house",
    country_code="US",
    language="en",
    depth=2,
    limit=1,
    offset=0,
    orderby="cpc,desc",
    filters=[
        ["cpc", ">", 0],
        "or", 
        [
            ["search_volume", ">", 0],
            "and",
            ["search_volume", "<=", 1000]
        ]
    ]
)

response = client.post("/v2/kwrd_finder_related_keywords_get", 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.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_finder_related_keywords_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 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
                {
                    keyword = "mountain house",
                    country_code = "US",
                    language = "en",
                    depth = 2,
                    limit = 10,
                    offset = 0,
                    orderby = "cpc,desc",
                    filters = new object[]
                    {
                        new object[] { "cpc", ">", 0 },
                        "or",
                        new object[]
                        {
                            new object[] { "search_volume", ">", 0 },
                            "and",
                            new object[] { "search_volume", "<=", 1000 }
                        }
                    }
                }
            };
            var pagePostResponse = await httpClient.PostAsync("v2/kwrd_finder_related_keywords_get", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await pagePostResponse.Content.ReadAsStringAsync());
            foreach (var result in obj.results)
            {
                var taskState = ((IEnumerable<dynamic>)result).First();
                if (taskState.status == "error")
                    Console.WriteLine($"\nError 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_finder_related_keywords_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_related_keywords_get");
        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("keyword", "mountain house");
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("depth", 2);
        postObj.put("limit", 1);
        postObj.put("offset", 0);
        postObj.put("orderby", "cpc,desc");
        postObj.put("filters", new Object[]{
            new Object[]
                {"cpc", ">", 0},
            "or",
            new Object[]{
                new Object[]
                    {"search_volume", ">", 0},
                "and",  
                new Object[]
                    {"search_volume", "<=", 1000}
            }
        });
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.5441 sec.",
    "results_count": 1,
    "results": {
        "11913049": {
            "post_id": "11913049",
            "task_id": 12937,
            "meta": {
                "keyword": "mountain house",
                "depth": 2,
                "limit": 1,
                "offset": 0,
                "orderby": "cpc,desc",
                "total_count": 71,
                "result_count": 1
            },
            "related": [
                {
                    "key": "freeze dried food reviews",
                    "country_code": "US",
                    "language": "en",
                    "search_volume": 50,
                    "competition": 1,
                    "cpc": 6.746295,
                    "categories": [
                        11889,
                        10113,
                        10081,
                        10082,
                        10422,
                        10010,
                        10014,
                        10015
                    ],
                    "history": [
                        {
                            "month": 2,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 1,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 12,
                            "year": 2017,
                            "search_volume": 10
                        },
                        {
                            "month": 11,
                            "year": 2017,
                            "search_volume": 10
                        },
                        {
                            "month": 10,
                            "year": 2017,
                            "search_volume": 40
                        },
                        {
                            "month": 9,
                            "year": 2017,
                            "search_volume": 70
                        },
                        {
                            "month": 8,
                            "year": 2017,
                            "search_volume": 70
                        },
                        {
                            "month": 7,
                            "year": 2017,
                            "search_volume": 70
                        },
                        {
                            "month": 6,
                            "year": 2017,
                            "search_volume": 90
                        },
                        {
                            "month": 5,
                            "year": 2017,
                            "search_volume": 90
                        },
                        {
                            "month": 4,
                            "year": 2017,
                            "search_volume": 110
                        },
                        {
                            "month": 3,
                            "year": 2017,
                            "search_volume": 70
                        }
                    ]
                }
            ]
        }
    }
}

You can specify the search depth, number of results you want to retrieve, filter and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
keyword string keyword
required field
UTF-8 encoding
all %## will be decoded (plus symbol ‘+’ will be decoded to a space character)
a keyword should be at least 3 characters long
the keywords will be changed to the lowercase format
country_code string ISO country code
required field
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
language string language
required field
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in the List of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
depth integer keyword search depth
required field
you can specify a level from 1 to 4
limit integer maximum number of returned keys
default value: 100
maximum value: 1000
offset integer offset in results array of returned keys
default value: 0
orderby string sorting of results
possible fields that can be used to sort results:
search_volume, competition, cpc
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
competition,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
search_volume,desc;cpc,desc
the following rule is applied by default:
search_volume,desc
filters array array with filters
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["cpc", ">", 0]
[["cpc", ">", 0], "and", ["search_volume", "in", [10,20]]]
[["search_volume", ">", 500], "or", [["cpc", ">", 1], "and", ["cpc", "<", 10]]]
      $field string the name of the filtered field
posible filtration parameters:
key, search_volume, competition, cpc
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in, like, not_like

use the following combination of filter fields and comparison operators:
key:
    like, not_like, =, <>
search_volume, competition, cpc:
    <, <=, >, >=, =, <>, in, not_in
If you want to filter the results array by the key value using like or not_like operators, you can use the following parameters:
["key", "like", "seo%"]      any values that start with “seo”
["key", "like", "%seo"]      any values that end with “seo”
["key", "like", "%seo%"]    any values that contain “seo”
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
like, not_like, =, <>:    string
<, <=, >, >=, =, <>:       integer
in, not_in:                       array

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            keyword string keyword received in a POST array
keyword is returned decoded %## (plus symbol ‘+’ is decoded as a space character)
            depth integer depth level for related keywords
            limit integer maximum number of returned keywords
            offset integer offset in results array of returned keywords
            orderby string sorting of results
            total_count integer total amount of results in our database by a specific request
            result_count integer number of elements in related array by a specific request
      related array results array of related
            key string related keyword
            country_code string ISO country code
            language string language
            search_volume integer average search volume
represents the (approximate) number of searches for the given keyword idea at google.com
            competition float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. Can accept values between 0 and 1 inclusive
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword
            categories array product and service categories
you can download the full list of possible categories
            history 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

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Similar Keywords

Using this method, you can receive similar terms for a keyword. Also, 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. These keywords are similar to a keyword you have specified or its variants that may be used in search queries. For instance, for “ice tea” keyword there will be such keywords as “ice tea net worth”, “green tea ice cream”, “green tea with ice” in the results array.

Get Similar Keywords

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();
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "keyword" => "ice tea",
        "country_code" => "US",
        "language" => "en",
        "limit" => 1,
        "offset" => 0,
        "orderby" => "cpc,desc",
        "filters" => array(
            array("cpc", ">", 0),
            "or",
            array(
                array("search_volume", ">", 0),
                "and",
                array("search_volume", "<=", 1000)
            )
        )
    );

    $get_result = $client->post("v2/kwrd_finder_similar_keywords_get", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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(
    keyword="ice tea",
    country_code="US",
    language="en",
    limit=1,
    offset=0,
    orderby="cpc,desc",
    filters=[
        ["cpc", ">", 0],
        "or", 
        [
            ["search_volume", ">", 0],
            "and",
            ["search_volume", "<=", 1000]
        ]
    ]
)

response = client.post("/v2/kwrd_finder_similar_keywords_get", 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.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_finder_similar_keywords_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 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
                {
                    keyword = "ice tea",
                    country_code = "US",
                    language = "en",
                    limit = 10,
                    offset = 0,
                    orderby = "cpc,desc",
                    filters = new object[]
                    {
                        new object[] { "cpc", ">", 0 },
                        "or",
                        new object[]
                        {
                            new object[] { "search_volume", ">", 0 },
                            "and",
                            new object[] { "search_volume", "<=", 1000 }
                        }
                    }
                }
            };
            var pagePostResponse = await httpClient.PostAsync("v2/kwrd_finder_similar_keywords_get", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await pagePostResponse.Content.ReadAsStringAsync());
            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_finder_similar_keywords_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_similar_keywords_get");
        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("keyword", "ice tea");
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("limit", 1);
        postObj.put("offset", 0);
        postObj.put("orderby", "cpc,desc");
        postObj.put("filters", new Object[]{
            new Object[]
                {"cpc", ">", 0},
            "or",
            new Object[]{
                new Object[]
                    {"search_volume", ">", 0},
                "and",
                new Object[]
                    {"search_volume", "<=", 1000}
            }
        });
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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": "12.2924 sec.",
    "results_count": 1,
    "results": {
        "11049": {
            "post_id": "11049",
            "task_id": 12939,
            "meta": {
                "keyword": "ice tea",
                "limit": 1,
                "offset": 0,
                "orderby": "cpc,desc",
                "total_count": 559,
                "result_count": 1
            },
            "similar": [
                {
                    "key": "ice tea quotes",
                    "country_code": "US",
                    "language": "en",
                    "search_volume": 50,
                    "competition": 0.006802721088435374,
                    "cpc": 8.44334,
                    "categories": [
                        10002,
                        10083,
                        10756,
                        13861,
                        10010,
                        10108,
                        10444,
                        11645,
                        10031
                    ],
                    "history": [
                        {
                            "month": 1,
                            "year": 2018,
                            "search_volume": 40
                        },
                        {
                            "month": 12,
                            "year": 2017,
                            "search_volume": 40
                        },
                        {
                            "month": 11,
                            "year": 2017,
                            "search_volume": 20
                        },
                        {
                            "month": 10,
                            "year": 2017,
                            "search_volume": 30
                        },
                        {
                            "month": 9,
                            "year": 2017,
                            "search_volume": 40
                        },
                        {
                            "month": 8,
                            "year": 2017,
                            "search_volume": 50
                        },
                        {
                            "month": 7,
                            "year": 2017,
                            "search_volume": 50
                        },
                        {
                            "month": 6,
                            "year": 2017,
                            "search_volume": 110
                        },
                        {
                            "month": 5,
                            "year": 2017,
                            "search_volume": 90
                        },
                        {
                            "month": 4,
                            "year": 2017,
                            "search_volume": 50
                        },
                        {
                            "month": 3,
                            "year": 2017,
                            "search_volume": 50
                        },
                        {
                            "month": 2,
                            "year": 2017,
                            "search_volume": 70
                        }
                    ]
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve, filter and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
keyword string keyword
required field
UTF-8 encoding
all %## will be decoded (plus symbol ‘+’ will be decoded to a space character)
a keyword should be at least 3 characters long
the keywords will be changed to the lowercase format
country_code string ISO country code
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
if you don’t specify a location, the results will be returned for all available locations
language string language
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in theList of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
if you don’t specify a language, the results will be returned for all languages
limit integer maximum number of returned keys
default value: 100
maximum value: 1000
offset integer offset in results array of returned keys
default value: 0
orderby string sorting of results
possible fields that can be used to sort results:
search_volume, competition, cpc
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
competition,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
search_volume,desc;cpc,desc
the following rule is applied by default:
search_volume,desc
filters array array with filters
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["cpc", ">", 0]
[["cpc", ">", 0], "and", ["search_volume", "in", [10,20]]]
[["search_volume", ">", 500], "or", [["cpc", ">", 1], "and", ["cpc", "<", 10]]]
      $field string the name of the filtered field
posible filtration parameters:
key, search_volume, competition, cpc
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in, like, not_like

use the following combination of filter fields and comparison operators:
key:
    like, not_like, =, <>
search_volume, competition, cpc:
    <, <=, >, >=, =, <>, in, not_in
If you want to filter the results array by the key value using like or not_like operators, you can use the following parameters:
["key", "like", "seo%"]      any values that start with “seo”
["key", "like", "%seo"]      any values that end with “seo”
["key", "like", "%seo%"]    any values that contain “seo”
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
like, not_like, =, <>:    string
<, <=, >, >=, =, <>:       integer
in, not_in:                       array

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            keyword string keyword received in a POST array
keyword is returned decoded %## (plus symbol ‘+’ is decoded as a space character)
            limit integer maximum number of returned keywords
            offset integer offset in results array of returned keywords
            orderby string sorting of results
            total_count integer total amount of results in our database by a specific request
            result_count integer number of elements in similar array by a specific request
      similar array results array of similar array
            key string similar keyword
            country_code string ISO country code
            language string language
            search_volume integer average search volume
represents the (approximate) number of searches for the given keyword idea at google.com
            competition float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. Can accept values between 0 and 1 inclusive
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword
            categories array product and service categories
you can download the full list of possible categories
            history 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

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Ranked Keywords

Using this method, you can get keywords for which a website is ranked. Also, you will get rankings and significant additional data for this keyword in the SERP.

Get Ranked Keywords

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "domain" => "dataforseo.com",
        "country_code" => "US",
        "language" => "en",
        "limit" => 1,
        "offset" => 0,
        "orderby" => "position,asc",
        "filters" => array(
            array("cpc", ">", 0),
            "and",
            array("search_volume", ">=", 1000)
        )
    );

    $get_result = $client->post("v2/kwrd_finder_ranked_keywords_get", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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="dataforseo.com",
    country_code="US",
    language="en",
    limit=1,
    offset=0,
    orderby="position,asc",
    filters=[
        ["cpc", ">", 0],
        "and", 
        ["search_volume", ">=", 1000]
    ]
)

response = client.post("/v2/kwrd_finder_ranked_keywords_get", 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.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_finder_ranked_keywords_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 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 = "dataforseo.com",
                    country_code = "US",
                    language = "en",
                    limit = 10,
                    offset = 0,
                    orderby = "position,desc",
                    filters = new object[]
                    {
                        new object[] { "cpc", ">", 0 },
                        "and",
                        new object[] { "search_volume", ">=", 1000 }
                    }
                }
            };
            var pagePostResponse = await httpClient.PostAsync("v2/kwrd_finder_ranked_keywords_get", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await pagePostResponse.Content.ReadAsStringAsync());
            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_finder_ranked_keywords_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_ranked_keywords_get");
        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", "dataforseo.com");
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("limit", 1);
        postObj.put("offset", 0);
        postObj.put("orderby", "cpc,desc");
        postObj.put("filters", new Object[]{
            new Object[]
                {"cpc", ">", 0},
            "and",
            new Object[]
                {"search_volume", ">=", 1000}
        });
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.4582 sec.",
    "results_count": 1,
    "results": {
        "11049": {
            "post_id": "11049",
            "task_id": 12942,
            "meta": {
                "domain": "dataforseo.com",
                "limit": 1,
                "offset": 0,
                "orderby": "position,asc",
                "total_count": 84,
                "actual_metric": {
                    "organic_count": 29,
                    "paid_count": 0,
                    "etv": 101,
                    "pos1": 0,
                    "pos2_3": 0,
                    "pos4_10": 0,
                    "pos11_20": 0,
                    "pos21_30": 4,
                    "pos31_40": 4,
                    "pos41_50": 0,
                    "pos51_60": 9,
                    "pos61_70": 4,
                    "pos71_80": 6,
                    "pos81_90": 1,
                    "pos91_100": 1,
                    "paid_pos1": 0,
                    "paid_pos2_3": 0,
                    "paid_pos4_10": 0,
                    "paid_pos11_20": 0,
                    "paid_pos21_100": 0
                },
                "result_count": 1
            },
            "ranked": [
                {
                    "key": "serps rank checker",
                    "exact_domain": "dataforseo.com",
                    "country_code": "US",
                    "language": "en",
                    "position": 22,
                    "url": "https://dataforseo.com/apis/serp-api",
                    "relative_url": "/apis/serp-api",
                    "results_count": 65400,
                    "etv": 2,
                    "traffic_cost": 16.75442,
                    "competition": 0,
                    "cpc": 8.37721,
                    "date": "2018-03-16T00:00:00+00:00",
                    "extra": "",
                    "search_volume": 1000,
                    "spell": "",
                    "title": "SERP rank position checker API ⓴⓲ SERP analysis and keyword ...",
                    "snippet": "DataForSEO ➤➤➤ SERP API ➤➤➤ Google SERP Rankings Checker API ✓✓✓ Great Speed, Clear Stats, Simple Pricing. Try for free now!",
                    "categories": [
                        10004,
                        10007,
                        10019,
                        10168,
                        10276,
                        10296
                    ]
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve, filter and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
domain string domain
required field
a domain should be specified without http:// and www
country_code string ISO country code
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
if you don’t specify a location, the results will be returned for all available locations
language string language
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in theList of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
if you don’t specify a language, the results will be returned for all languages
type string SERP type
can have the following values: organic, paid
default value: organic
limit integer maximum number of returned keys
default value: 100
maximum value: 1000
offset integer offset in results array of returned keys
default value: 0
orderby string sorting of results
possible fields that can be used to sort results:
position, results_count, etv, traffic_cost, competition, cpc, search_volume
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
competition,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
search_volume,desc;cpc,desc
the following rule is applied by default:
position,asc
filters array array with filters
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["cpc", ">", 0]
[["cpc", ">", 0], "and", ["search_volume", "in", [10,20]]]
[["search_volume", ">", 1000], "and", [["position", ">", 0], "and", ["position", "<", 11]]]
      $field string the name of the filtered field
posible filtration parameters:
position, results_count, etv, traffic_cost, competition, cpc, search_volume, exact_domain, relative_url, title, snippet, key, categories
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in, like, not_like, has

use the following combination of filter fields and comparison operators:
exact_domain, relative_url, title, snippet, key:
    like, not_like, =, <>
position, results_count, etv, traffic_cost, competition, cpc, search_volume:
    <, <=, >, >=, =, <>, in, not_in
categories:
    has
If you want to filter the results array by the key value using like or not_like operators, you can use the following parameters:
["key", "like", "seo%"]      any values that start with “seo”
["key", "like", "%seo"]      any values that end with “seo”
["key", "like", "%seo%"]    any values that contain “seo”
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
like, not_like, =, <>:           string
<, <=, >, >=, =, <>, has:     integer
in, not_in:                              array

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

You will receive array from the API server in the results field where you will find 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 in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            domain string specified domain
            limit integer maximum number of returned keywords
            offset integer offset in results array of returned keywords
            orderby string sorting of results
            total_count integer total amount of results in our database by a specific request
            result_count integer number of elements in ranked array by a specific request
            actual_metric array actual metrics for a specified domain
                  organic_count integer number of organic results in SERP
results will be available if you set organic at the type field
                  paid_count integer number of paid results in SERP
results will be available if you set paid at the type field
                  etv integer estimated traffic to domain based on organic and paid SERP data in system
                  pos1 integer number of organic SERP which contain domain at the first place
                  pos2_3 integer number of organic SERP which contain domain at the second and third place
                  pos4_10 integer number of organic SERP which contain domain at the 4-10 place
                  pos11_20 integer number of organic SERP which contain domain at the 11-20 place
                  pos21_30 integer number of organic SERP which contain domain at the 21-30 place
                  pos31_40 integer number of organic SERP which contain domain at the 31-40 place
                  pos41_50 integer number of organic SERP which contain domain at the 41-50 place
                  pos51_60 integer number of organic SERP which contain domain at the 51-60 place
                  pos61_70 integer number of organic SERP which contain domain at the 61-70 place
                  pos71_80 integer number of organic SERP which contain domain at the 71-80 place
                  pos81_90 integer number of organic SERP which contain domain at the 81-90 place
                  pos91_100 integer number of organic SERP which contain domain at the 91-100 place
                  paid_pos1 integer number of paid SERP which contain domain at the first place
                  paid_pos2_3 integer number of paid SERP which contain domain at the second and third place
                  paid_pos4_10 integer number of paid SERP which contain domain at the 4-10 place
                  paid_pos11_20 integer number of paid SERP which contain domain at the 11-20 place
                  paid_pos21_100 integer number of paid SERP which contain domain at the 21-100 place
      ranked array results array of ranked
            key string keyword in SERP
            country_code string ISO country code
            language string language
            exact_domain string exact domain
can be subdomain
            position integer position in SERP
            url string relevant full URL in the SERP
            relative_url string relative path and query from url
            results_count integer total number of results in the SERP
            etv integer estimated traffic value based on search volume and domain position
            traffic_cost float traffic cost
the value is calculated as ETV*CPC
            competition float Google AdWords competition value
            cpc float cost per click from Google AdWords
            date string date update
            extra string extra elements in SERP
can be equal:
top_stories, featured_snippet, people_also_ask, local_pack, carousel, images, map, video, twitter, app, shopping, google_flights, jobs, answer_box, related_search, knowledge_graph, google_review
            search_volume integer number of searches per month
            spell string search engine keyword autocorrection
            title string title of current SERP result
            snippet string snippet of current SERP result
            categories array product and service categories
you can download the full list of possible categories

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Keywords for Terms

Using this option, you can retrieve suggestions for specified keywords. In addition to the keywords, you will also receive search volume for the last month, search volume trend for the previous 12 months (that will let you estimate search volume dynamics), current cost-per-click and competition level for paid search. You also can set a number of keywords which you want to get using the limit field.

Get Keywords for Terms

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "keywords" => array("seo"),
        "country_code" => "US",
        "language" => "en",
        "limit" => 20
    );

    $get_result = $client->post("v2/kwrd_finder_kwrd_for_terms", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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(
    keywords=[
        "seo"
    ],
    country_code="US",
    language="en",
    limit=20
)

response = client.post("/v2/kwrd_finder_kwrd_for_terms", 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.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_finder_kwrd_for_terms()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),
                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random();
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    keywords = new[]
                    {
                        "seo"
                    },
                    country_code = "US",
                    language = "en",
                    limit = 20
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_finder_kwrd_for_terms", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            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_finder_kwrd_for_terms() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_kwrd_for_terms");
        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("keywords", new Object[]{
            "seo"
        });
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("limit", 20);
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.7020 sec.",
    "results_count": 1,
    "results": {
        "358941": {
            "post_id": "358941",
            "task_id": 891186,
            "meta": {
                "country_code": "US",
                "language": "en",
                "keywords": [
                    "seo"
                ],
                "limit": 20,
                "sort_by": "relevance",
                "result_count": 20
            },
            "result": [
                {
                    "key": "seo",
                    "country_code": "US",
                    "language": "en",
                    "search_volume": 135000,
                    "competition": 0.3620891386896943,
                    "cpc": 16.288592,
                    "history": [
                        {
                            "month": 2,
                            "year": 2019,
                            "search_volume": 135000
                        },
                        {
                            "month": 1,
                            "year": 2019,
                            "search_volume": 135000
                        },
                        {
                            "month": 12,
                            "year": 2018,
                            "search_volume": 110000
                        },
                        {
                            "month": 11,
                            "year": 2018,
                            "search_volume": 110000
                        },
                        {
                            "month": 10,
                            "year": 2018,
                            "search_volume": 135000
                        },
                        {
                            "month": 9,
                            "year": 2018,
                            "search_volume": 110000
                        },
                        {
                            "month": 8,
                            "year": 2018,
                            "search_volume": 110000
                        },
                        {
                            "month": 7,
                            "year": 2018,
                            "search_volume": 110000
                        },
                        {
                            "month": 6,
                            "year": 2018,
                            "search_volume": 110000
                        },
                        {
                            "month": 5,
                            "year": 2018,
                            "search_volume": 135000
                        },
                        {
                            "month": 4,
                            "year": 2018,
                            "search_volume": 135000
                        },
                        {
                            "month": 3,
                            "year": 2018,
                            "search_volume": 135000
                        }
                    ],
                    "categories": [
                        10004,
                        10007,
                        10276,
                        11088,
                        12376,
                        13152,
                        13316,
                        13418
                    ]
                },
                {
                    "key": "get google to crawl your website",
                    "country_code": "US",
                    "language": "en",
                    "search_volume": 10,
                    "competition": 0.07142857142857142,
                    "cpc": 0,
                    "history": [
                        {
                            "month": 12,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 11,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 10,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 9,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 8,
                            "year": 2018,
                            "search_volume": 0
                        },
                        {
                            "month": 7,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 6,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 5,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 4,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 3,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 2,
                            "year": 2018,
                            "search_volume": 10
                        },
                        {
                            "month": 1,
                            "year": 2018,
                            "search_volume": 10
                        }
                    ],
                    "categories": [
                        10004,
                        10007,
                        10276,
                        11088,
                        12376,
                        13152,
                        13316,
                        13418
                    ]
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
country_code string ISO country code
required field
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
language string language
required field
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in theList of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
keywords array array of keywords
required field
UTF-8 encoding
all %## will be decoded (plus symbol ‘+’ will be decoded to a space character)
a keywords should be at least 3 characters long
the keywords will be changed to the lowercase format
maximum 200 keywords can be specified
limit integer maximum number of returned keys
optional field
default value: 700
maximum value: 1000
sort_by string column to sort the results
optional field
can have the following values: “sv”, “relevance”
default value: “relevance”
close_variants boolean close variants
optional field
to show only the results which are highly relevant to the provided keywords, specify true value
default value: false

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            keywords array specified keywords
            limit integer maximum number of returned keywords
            sort_by string sorting of results
            result_count integer number of elements in result array by a specific request
      result array result array of keywords
            key string keyword
            country_code string ISO country code
            language string language
            search_volume integer number of searches per month
            competition float Google AdWords competition value
            cpc float cost per click from Google AdWords
            history array searches history
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
            categories array product and service categories
you can download the full list of possible categories

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

SERP Keywords Competitors

Using this option, you can retrieve SERP competitors for specified keywords.

Get SERP Keywords Competitors

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "keywords" => array("phone", "buy"),
        "country_code" => "US",
        "language" => "en",
        "limit" => 20
    );

    $get_result = $client->post("v2/kwrd_finder_serp_competitors", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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(
    keywords=[
       "phone", "buy"
    ],
    country_code="US",
    language="en",
    limit=20
)

response = client.post("/v2/kwrd_finder_serp_competitors", 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.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_finder_serp_competitors()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),
                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random();
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    country_code = "US",
                    language = "en",
                    keywords = new[]
                    {
                        "seo",
                        "site checker"
                    }
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_finder_serp_competitors", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            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_finder_serp_competitors() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_serp_competitors");
        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("keywords", new Object[]{
            "phone", "buy"
        });
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("limit", 20);
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.1363 sec.",
    "results_count": 1,
    "results": {
        "874654654": {
            "post_id": "874654654",
            "task_id": 1066830,
            "meta": {
                "country_code": "US",
                "language": "en",
                "keywords": [
                    "phone",
                    "buy"
                ],
                "match_subdomains": true,
                "type": "organic",
                "limit": 20,
                "offset": 0,
                "orderby": "rating,desc",
                "result_count": 20
            },
            "domains": [
                {
                    "domain": "www.verizonwireless.com",
                    "avg_position": 18.5,
                    "median_position": 18.5,
                    "keywords_count": 2,
                    "rating": 163,
                    "etv": 9523,
                    "visibility": 0.4
                },
                {
                    "domain": "www.wsj.com",
                    "avg_position": 21,
                    "median_position": 21,
                    "keywords_count": 2,
                    "rating": 158,
                    "etv": 1747,
                    "visibility": 0.3
                },
                {
                    "domain": "zoom.us",
                    "avg_position": 25.5,
                    "median_position": 25.5,
                    "keywords_count": 2,
                    "rating": 149,
                    "etv": 875,
                    "visibility": 0
                },
                {
                    "domain": "www.microsoft.com",
                    "avg_position": 28.5,
                    "median_position": 28.5,
                    "keywords_count": 2,
                    "rating": 143,
                    "etv": 905,
                    "visibility": 0.05
                },
                {
                    "domain": "www.t-mobile.com",
                    "avg_position": 38,
                    "median_position": 38,
                    "keywords_count": 2,
                    "rating": 124,
                    "etv": 17362,
                    "visibility": 0.6
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
country_code string ISO country code
required field
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
language string language
required 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
keywords array array of keywords
required field
UTF-8 encoding
all %## will be decoded (plus symbol ‘+’ will be decoded to a space character)
a keyword should be at least 3 characters long
keywords will be converted to lowercase
maximum 200 keywords can be specified
match_subdomains boolean match subdomains
optional field
if you specify a false value in the field, the subdomains will be ignored when grouping
default value: true
type string SERP type
can have the following values: organic, paid
default value: organic
limit integer maximum number of returned results
optional field
default value: 100
maximum value: 1000
offset integer offset in results array of returned keys
default value: 0
orderby string sorting of results
possible fields that can be used to sort results:
avg_position, median_position, keywords_count, rating, etv, visibility
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
etv,desc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
etv,desc;rating,desc
by default the following rule is applied:
rating,desc
filters array array with filters
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["etv", ">", 1000]
[["etv", ">", 1000], "and", ["visibility", ">", 0]]
[["etv", ">", 1000], "and", [["visibility", ">", 0], "and", ["visibility", "<", 0.5]]]
The following three fields must be specified if you apply a filter
      $field string the name of the filtered field
posible filtration parameters:
avg_position, median_position, keywords_count, rating, etv, visibility
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>

use the following combination of filter fields and comparison operators:
avg_position, median_position, keywords_count, rating, etv, visibility:
    <, <=, >, >=, =, <>
      $value integer comparison value
use the following combination of comparison operators and data types:
<, <=, >, >=, =, <>:     integer

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            country_code string specified country code
            language string specified language
            keywords array specified keywords
            match_subdomains boolean specified subdomains matching
            type string specified SERP type
            limit integer maximum number of returned results
            offset integer specified offset in results array
            orderby string sorting of results
            result_count integer number of elements in domains array by a specific request
      domains array result array
            domain string grouping field, can be a domain or subdomain
            avg_position float average domain position in SERP intersections
            median_position float median domain position in SERP intersections
            keywords_count integer count of intersected keywords
            rating integer calculated as the sum(100 - position)
            etv integer summary estimated traffic value
            visibility float calculated as the sum of keywords positions
Keywords with positions in the range from 1 to 10 are assigned the visibility index from 1 to 0.1, respectively. Keywords with positions in the range from 11 to 20 have the fixed visibility index of 0.05. Keywords with positions from 20 to 100 have the visibility index equal to 0

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Relevant Pages

Using this method you can get SERP metrics for relevant pages of a website based on a specific location.

Get Relevant Pages

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "domain" => "rankactive.com",
        "country_code" => "US",
        "language" => "en",
        "limit" => 3
    );

    $get_result = $client->post("v2/kwrd_finder_relevant_pages_get", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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="rankactive.com",
    country_code="US",
    language="en",
    limit=3
)

response = client.post("/v2/kwrd_finder_relevant_pages_get", 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.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_finder_relevant_pages_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 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 = "rankactive.com",
                    country_code = "US",
                    language = "en",
                    limit = 10
                }
            };
            var pagePostResponse = await httpClient.PostAsync("v2/kwrd_finder_relevant_pages_get", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await pagePostResponse.Content.ReadAsStringAsync());
            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_finder_relevant_pages_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_relevant_pages_get");
        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", "dataforseo.com");
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("limit", 3);
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.1752 sec.",
    "results_count": 1,
    "results": {
        "11913049": {
            "post_id": "11913049",
            "task_id": 12947,
            "meta": {
                "domain": "rankactive.com",
                "limit": 3,
                "offset": 0,
                "orderby": "organic_count,desc",
                "total_count": 19,
                "result_count": 3
            },
            "relevant_pages": [
                {
                    "page_address": "rankactive.com/products/rank-tracker",
                    "country_code": "US",
                    "language": "en",
                    "organic_count": 217,
                    "paid_count": 0,
                    "etv": 161,
                    "pos1": 0,
                    "pos2_3": 0,
                    "pos4_10": 3,
                    "pos11_20": 34,
                    "pos21_30": 64,
                    "pos31_40": 39,
                    "pos41_50": 20,
                    "pos51_60": 17,
                    "pos61_70": 18,
                    "pos71_80": 10,
                    "pos81_90": 9,
                    "pos91_100": 3,
                    "paid_pos1": 0,
                    "paid_pos2_3": 0,
                    "paid_pos4_10": 0,
                    "paid_pos11_20": 0,
                    "paid_pos21_100": 0
                },
                {
                    "page_address": "rankactive.com/lp/rank-tracker/google-keyword-position-checker-api",
                    "country_code": "US",
                    "language": "en",
                    "organic_count": 26,
                    "paid_count": 0,
                    "etv": 3,
                    "pos1": 0,
                    "pos2_3": 0,
                    "pos4_10": 4,
                    "pos11_20": 4,
                    "pos21_30": 7,
                    "pos31_40": 2,
                    "pos41_50": 1,
                    "pos51_60": 5,
                    "pos61_70": 1,
                    "pos71_80": 1,
                    "pos81_90": 0,
                    "pos91_100": 1,
                    "paid_pos1": 0,
                    "paid_pos2_3": 0,
                    "paid_pos4_10": 0,
                    "paid_pos11_20": 0,
                    "paid_pos21_100": 0
                },
                {
                    "page_address": "rankactive.com/",
                    "country_code": "US",
                    "language": "en",
                    "organic_count": 15,
                    "paid_count": 0,
                    "etv": 13,
                    "pos1": 0,
                    "pos2_3": 0,
                    "pos4_10": 0,
                    "pos11_20": 1,
                    "pos21_30": 3,
                    "pos31_40": 1,
                    "pos41_50": 0,
                    "pos51_60": 1,
                    "pos61_70": 3,
                    "pos71_80": 2,
                    "pos81_90": 1,
                    "pos91_100": 3,
                    "paid_pos1": 0,
                    "paid_pos2_3": 0,
                    "paid_pos4_10": 0,
                    "paid_pos11_20": 0,
                    "paid_pos21_100": 0
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve, filter and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
domain string domain
required field
a domain should be specified without http:// and www
country_code string ISO country code
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
if you don’t specify a location, the results will be returned for all available locations
language string language
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in theList of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
if you don’t specify a language, the results will be returned for all languages
type string SERP type
can have the following values: organic, paid
default value: organic
limit integer maximum number of returned pages
default value: 100
maximum value: 1000
offset integer offset in results array of returned pages
default value: 0
orderby string sorting of results
possible fields that can be used to sort results:
organic_count, paid_count, etv
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
etv,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
etv,desc;organic_count,desc
the following rule is applied by default:
organic_count,desc
filters array array with filters
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["paid_count", ">", 0]
[["etv", ">", 10], "and", ["paid_count", ">", 0]]
[["etv", ">", 10], "and", [["paid_count", ">", 0], "and", ["organic_count", ">", 10]]]
      $field string the name of the filtered field
posible filtration parameters:
page_address,organic_count, paid_count, etv
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in, like, not_like

use the following combination of filter fields and comparison operators:
page_address:
    like, not_like, =, <>
organic_count, paid_count, etv:
    <, <=, >, >=, =, <>, in, not_in
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
like, not_like, =, <>:    string
<, <=, >, >=, =, <>:       integer
in, not_in:                       array

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

You will receive array from the API server in the results field where you will find 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 in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            domain string specified domain
            limit integer maximum number of returned keywords
            offset integer offset in results array of returned keywords
            orderby string sorting of results
            total_count integer total amount of results in our database by a specific request
            result_count integer number of elements in relevant_pages array by a specific request
      relevant_pages array results array of relevant_pages
            page_address string link of relevant page
            country_code string ISO country code
            language string language
            organic_count integer number of organic results in SERP
results will be available if you set organic at the type field
            paid_count integer number of paid results in SERP
results will be available if you set paid at the type field
            etv integer estimated traffic to domain based on organic and paid SERP data in system
            pos1 integer number of organic SERP which contain domain at the first place
            pos2_3 integer number of organic SERP which contain domain at the second and third place
            pos4_10 integer number of organic SERP which contain domain at the 4-10 place
            pos11_20 integer number of organic SERP which contain domain at the 11-20 place
            pos21_30 integer number of organic SERP which contain domain at the 21-30 place
            pos31_40 integer number of organic SERP which contain domain at the 31-40 place
            pos41_50 integer number of organic SERP which contain domain at the 41-50 place
            pos51_60 integer number of organic SERP which contain domain at the 51-60 place
            pos61_70 integer number of organic SERP which contain domain at the 61-70 place
            pos71_80 integer number of organic SERP which contain domain at the 71-80 place
            pos81_90 integer number of organic SERP which contain domain at the 81-90 place
            pos91_100 integer number of organic SERP which contain domain at the 91-100 place
            paid_pos1 integer number of paid SERP which contain domain at the first place
            paid_pos2_3 integer number of paid SERP which contain domain at the second and third place
            paid_pos4_10 integer number of paid SERP which contain domain at the 4-10 place
            paid_pos11_20 integer number of paid SERP which contain domain at the 11-20 place
            paid_pos21_100 integer number of paid SERP which contain domain at the 21-100 place

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Subdomains

Using this method you can get SERP data for subdomains of a website based on a specific location.

Get Subdomains

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "domain" => "dataforseo.com",
        "country_code" => "US",
        "language" => "en",
        "limit" => 3
    );

    $get_result = $client->post("v2/kwrd_finder_subdomains_get", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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="rankactive.com",
    country_code="US",
    language="en",
    limit=3
)

response = client.post("/v2/kwrd_finder_subdomains_get", 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.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_finder_subdomains_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 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 = "rankactive.com",
                    country_code = "US",
                    language = "en",
                    limit = 3
                }
            };
            var pagePostResponse = await httpClient.PostAsync("v2/kwrd_finder_subdomains_get", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await pagePostResponse.Content.ReadAsStringAsync());
            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_finder_subdomains_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_subdomains_get");
        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", "rankactive.com");
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("limit", 3);
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.1327 sec.",
    "results_count": 1,
    "results": {
        "11913049": {
            "post_id": "11913049",
            "task_id": 12949,
            "meta": {
                "domain": "dataforseo.com",
                "limit": 3,
                "offset": 0,
                "orderby": "organic_count,desc",
                "total_count": 1,
                "result_count": 3
            },
            "subdomains": [
                {
                    "exact_domain": "docs.dataforseo.com",
                    "country_code": "US",
                    "language": "en",
                    "organic_count": 4,
                    "paid_count": 0,
                    "etv": 0,
                    "pos1": 0,
                    "pos2_3": 0,
                    "pos4_10": 0,
                    "pos11_20": 0,
                    "pos21_30": 0,
                    "pos31_40": 0,
                    "pos41_50": 0,
                    "pos51_60": 1,
                    "pos61_70": 1,
                    "pos71_80": 1,
                    "pos81_90": 1,
                    "pos91_100": 0,
                    "paid_pos1": 0,
                    "paid_pos2_3": 0,
                    "paid_pos4_10": 0,
                    "paid_pos11_20": 0,
                    "paid_pos21_100": 0
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve, filter and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
domain string domain
required field
a domain should be specified without http:// and www
country_code string ISO country code
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
if you don’t specify a location, the results will be returned for all available locations
language string language
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in theList of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
if you don’t specify a language, the results will be returned for all languages
type string SERP type
can have the following values: organic, paid
default value: organic
limit integer maximum number of returned domains
default value: 100
maximum value: 1000
offset integer offset in results array of returned domains
default value: 0
orderby string sorting of results
possible fields that can be used to sort results:
organic_count, paid_count, etv
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
etv,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
etv,desc;organic_count,desc
the following rule is applied by default:
organic_count,desc
filters array array with filters
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["paid_count", ">", 0]
[["etv", ">", 10], "and", ["paid_count", ">", 0]]
[["etv", ">", 10], "and", [["paid_count", ">", 0], "and", ["organic_count", ">", 10]]]
      $field string the name of the filtered field
posible filtration parameters:
exact_domain,organic_count, paid_count, etv
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in, like, not_like

use the following combination of filter fields and comparison operators:
exact_domain:
    like, not_like, =, <>
organic_count, paid_count, etv:
    <, <=, >, >=, =, <>, in, not_in
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
like, not_like, =, <>:    string
<, <=, >, >=, =, <>:       integer
in, not_in:                       array

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

You will receive array from the API server in the results field where you will find 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 in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            domain string specified domain
            limit integer maximum number of returned keywords
            offset integer offset in results array of returned keywords
            orderby string sorting of results
            total_count integer total amount of results in our database by a specific request
            result_count integer number of elements in subdomains array by a specific request
      subdomains array results array of subdomains
            exact_domain string exact domain
            country_code string ISO country code
            language string language
            organic_count integer number of organic results in SERP
results will be available if you set organic at the type field
            paid_count integer number of paid results in SERP
results will be available if you set paid at the type field
            etv integer estimated traffic to domain based on organic and paid SERP data in system
            pos1 integer number of organic SERP which contain domain at the first place
            pos2_3 integer number of organic SERP which contain domain at the second and third place
            pos4_10 integer number of organic SERP which contain domain at the 4-10 place
            pos11_20 integer number of organic SERP which contain domain at the 11-20 place
            pos21_30 integer number of organic SERP which contain domain at the 21-30 place
            pos31_40 integer number of organic SERP which contain domain at the 31-40 place
            pos41_50 integer number of organic SERP which contain domain at the 41-50 place
            pos51_60 integer number of organic SERP which contain domain at the 51-60 place
            pos61_70 integer number of organic SERP which contain domain at the 61-70 place
            pos71_80 integer number of organic SERP which contain domain at the 71-80 place
            pos81_90 integer number of organic SERP which contain domain at the 81-90 place
            pos91_100 integer number of organic SERP which contain domain at the 91-100 place
            paid_pos1 integer number of paid SERP which contain domain at the first place
            paid_pos2_3 integer number of paid SERP which contain domain at the second and third place
            paid_pos4_10 integer number of paid SERP which contain domain at the 4-10 place
            paid_pos11_20 integer number of paid SERP which contain domain at the 11-20 place
            paid_pos21_100 integer number of paid SERP which contain domain at the 21-100 place

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Competitors Domain

Using this option, you can get information about competitive domains for the specified site, which will be determined by the intersection of keywords.

Get Competitors Domain

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "domain" => "dataforseo.com",
        "country_code" => "US",
        "language" => "en",
        "limit" => 5
    );

    $get_result = $client->post("v2/kwrd_finder_domain_competitors", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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="dataforseo.com",
    country_code="US",
    language="en",
    limit=5
)

response = client.post("/v2/kwrd_finder_domain_competitors", 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.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_finder_domain_competitors()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),
                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random();
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    country_code = "US",
                    language = "en",
                    domain = "dataforseo.com"
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_finder_domain_competitors", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            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_finder_domain_competitors() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_domain_competitors");
        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", "dataforseo.com");
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("limit", 5);
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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": "5.2832 sec.",
    "results_count": 1,
    "results": {
        "874654654": {
            "post_id": "874654654",
            "task_id": 1113680,
            "meta": {
                "country_code": "US",
                "language": "en",
                "domain": "dataforseo.com",
                "type": "organic",
                "limit": 5,
                "orderby": "intersections,desc",
                "result_count": 5
            },
            "competitors": [
                {
                    "domain": "dataforseo.com",
                    "intersections": 916,
                    "pos_sum": 56325,
                    "avg_pos": 61.49017467248908,
                    "metrics": {
                        "organic_count": 916,
                        "paid_count": 9,
                        "etv": 663,
                        "pos1": 3,
                        "pos2_3": 7,
                        "pos4_10": 23,
                        "pos11_20": 21,
                        "pos21_30": 50,
                        "pos31_40": 82,
                        "pos41_50": 98,
                        "pos51_60": 145,
                        "pos61_70": 129,
                        "pos71_80": 121,
                        "pos81_90": 123,
                        "pos91_100": 114,
                        "paid_pos1": 3,
                        "paid_pos2_3": 5,
                        "paid_pos4_10": 1,
                        "paid_pos11_20": 0,
                        "paid_pos21_100": 0
                    }
                },
                {
                    "domain": "quora.com",
                    "intersections": 824,
                    "pos_sum": 25976,
                    "avg_pos": 31.524271844660195,
                    "metrics": {
                        "organic_count": 32274509,
                        "paid_count": 0,
                        "etv": 216701838,
                        "pos1": 560100,
                        "pos2_3": 1288017,
                        "pos4_10": 4817374,
                        "pos11_20": 5763842,
                        "pos21_30": 4612861,
                        "pos31_40": 3614436,
                        "pos41_50": 2940681,
                        "pos51_60": 2478975,
                        "pos61_70": 2087977,
                        "pos71_80": 1725691,
                        "pos81_90": 1403220,
                        "pos91_100": 981335,
                        "paid_pos1": 0,
                        "paid_pos2_3": 0,
                        "paid_pos4_10": 0,
                        "paid_pos11_20": 0,
                        "paid_pos21_100": 0
                    }
                },
                {
                    "domain": "moz.com",
                    "intersections": 773,
                    "pos_sum": 11076,
                    "avg_pos": 14.328589909443727,
                    "metrics": {
                        "organic_count": 288127,
                        "paid_count": 380,
                        "etv": 3380708,
                        "pos1": 3752,
                        "pos2_3": 5318,
                        "pos4_10": 19557,
                        "pos11_20": 25837,
                        "pos21_30": 26214,
                        "pos31_40": 28344,
                        "pos41_50": 30794,
                        "pos51_60": 31381,
                        "pos61_70": 31121,
                        "pos71_80": 30266,
                        "pos81_90": 29686,
                        "pos91_100": 25857,
                        "paid_pos1": 122,
                        "paid_pos2_3": 243,
                        "paid_pos4_10": 15,
                        "paid_pos11_20": 0,
                        "paid_pos21_100": 0
                    }
                },
                {
                    "domain": "google.com",
                    "intersections": 761,
                    "pos_sum": 22402,
                    "avg_pos": 29.437582128777922,
                    "metrics": {
                        "organic_count": 87318958,
                        "paid_count": 6079,
                        "etv": 3440879886,
                        "pos1": 536915,
                        "pos2_3": 570902,
                        "pos4_10": 2843155,
                        "pos11_20": 7069719,
                        "pos21_30": 7558212,
                        "pos31_40": 8244961,
                        "pos41_50": 8918941,
                        "pos51_60": 9761893,
                        "pos61_70": 10772621,
                        "pos71_80": 11361769,
                        "pos81_90": 11114253,
                        "pos91_100": 8565617,
                        "paid_pos1": 4418,
                        "paid_pos2_3": 1476,
                        "paid_pos4_10": 185,
                        "paid_pos11_20": 0,
                        "paid_pos21_100": 0
                    }
                },
                {
                    "domain": "ahrefs.com",
                    "intersections": 685,
                    "pos_sum": 17087,
                    "avg_pos": 24.944525547445256,
                    "metrics": {
                        "organic_count": 82321,
                        "paid_count": 0,
                        "etv": 1417521,
                        "pos1": 1769,
                        "pos2_3": 2648,
                        "pos4_10": 7451,
                        "pos11_20": 7201,
                        "pos21_30": 7660,
                        "pos31_40": 7615,
                        "pos41_50": 7954,
                        "pos51_60": 8022,
                        "pos61_70": 8081,
                        "pos71_80": 8139,
                        "pos81_90": 8324,
                        "pos91_100": 7457,
                        "paid_pos1": 0,
                        "paid_pos2_3": 0,
                        "paid_pos4_10": 0,
                        "paid_pos11_20": 0,
                        "paid_pos21_100": 0
                    }
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
country_code string ISO country code
required field
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
language string language
required 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
domain string domain
required field
a domain should be specified without http://, https:// and www
type string SERP type
can have the following values: organic, paid
default value: organic
limit integer maximum number of returned results
optional field
default value: 100
maximum value: 1000
orderby string sorting of results
possible fields that can be used to sort results:
intersections, pos_sum, avg_pos
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
intersections,desc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
intersections,desc;pos_sum,desc
by default the following rule is applied:
intersections,desc

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            country_code string specified country code
            language string specified language
            domain string specified domain
            type string specified SERP type
            limit integer specified maximum number of returned results
            orderby string specified sorting of results
            result_count integer number of elements in competitors array by a specific request
      competitors array result array
            domain string competing domain name
            intersections integer count of keywords intersections
            pos_sum integer sum of the positions of a competing domain
            avg_pos float average position of a competing domain
            metrics array domain metrics info
                  organic_count integer number of organic results in SERP
results will be available if you set organic at the type field
                  paid_count integer number of paid results in SERP
results will be available if you set paid at the type field
                  etv integer estimated traffic to domain based on organic and paid SERP data in the system
                  pos1 integer number of domains keywords ranking 1 in organic SERP
                  pos2_3 integer number of domains keywords ranking 2-3 in organic SERP
                  pos4_10 integer number of domains keywords ranking 4-10 in organic SERP
                  pos11_20 integer number of domains keywords ranking 11-20 in organic SERP
                  pos21_30 integer number of domains keywords ranking 21-30 in organic SERP
                  pos31_40 integer number of domains keywords ranking 31-40 in organic SERP
                  pos41_50 integer number of domains keywords ranking 41-50 in organic SERP
                  pos51_60 integer number of domains keywords ranking 51-60 in organic SERP
                  pos61_70 integer number of domains keywords ranking 61-70 in organic SERP
                  pos71_80 integer number of domains keywords ranking 71-80 in organic SERP
                  pos81_90 integer number of domains keywords ranking 81-90 in organic SERP
                  pos91_100 integer number of domains keywords ranking 91-100 in organic SERP
                  paid_pos1 integer number of domains keywords ranking 1 in paid SERP
                  paid_pos2_3 integer number of domains keywords ranking 2-3 in paid SERP
                  paid_pos4_10 integer number of domains keywords ranking 4-10 in paid SERP
                  paid_pos11_20 integer number of domains keywords ranking 11-20 in paid SERP
                  paid_pos21_100 integer number of domains keywords ranking 21-100 in paid SERP

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Ranked Categories

Using this option, you can check the categories of keywords for which a domain is ranked.

Get Ranked Categories

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "domain" => "hide.co.uk",
        "country_code" => "GB",
        "language" => "en",
        "limit" => 10,
        "orderby" => "organic_count,desc"
    );

    $get_result = $client->post("v2/kwrd_finder_categories_for_domain_get", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

$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

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="hide.co.uk",
    country_code="GB",
    language="en",
    limit=10,
    orderby="organic_count,desc"
)

response = client.post("/v2/kwrd_finder_categories_for_domain_get", 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.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_finder_categories_for_domain_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 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 = "hide.co.uk",
                    country_code = "GB",
                    language = "en",
                    limit = 10,
                    orderby = "organic_count,desc"
                }
            };
            var pagePostResponse = await httpClient.PostAsync("v2/kwrd_finder_categories_for_domain_get", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await pagePostResponse.Content.ReadAsStringAsync());
            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_finder_categories_for_domain_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_categories_for_domain_get");
        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", "hide.co.uk");
        postObj.put("country_code", "GB");
        postObj.put("language", "en");
        postObj.put("limit", 10);
        postObj.put("orderby", "organic_count,desc");
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.7265 sec.",
    "results_count": 1,
    "results": {
        "11913049": {
            "post_id": "11dfg913049",
            "task_id": 1157987462,
            "meta": {
                "domain": "hide.co.uk",
                "limit": 10,
                "offset": 0,
                "orderby": "organic_count,desc",
                "type": "organic",
                "total_count": 39,
                "result_count": 10
            },
            "categories": [
                {
                    "category": [],
                    "country_code": "GB",
                    "language": "en",
                    "organic_count": 493,
                    "paid_count": 0,
                    "organic_traffic_cost": 3085.219878,
                    "paid_traffic_cost": 0,
                    "etv": 3687,
                    "date": "2019-05-16 00:00:00+00:00",
                    "pos1": 42,
                    "pos2_3": 3,
                    "pos4_10": 19,
                    "pos11_20": 34,
                    "pos21_30": 44,
                    "pos31_40": 41,
                    "pos41_50": 41,
                    "pos51_60": 43,
                    "pos61_70": 57,
                    "pos71_80": 59,
                    "pos81_90": 47,
                    "pos91_100": 63,
                    "paid_pos1": 0,
                    "paid_pos2_3": 0,
                    "paid_pos4_10": 0,
                    "paid_pos11_20": 0,
                    "paid_pos21_100": 0
                },
                {
                    "category": [
                        10020
                    ],
                    "country_code": "GB",
                    "language": "en",
                    "organic_count": 161,
                    "paid_count": 0,
                    "organic_traffic_cost": 7338.505013,
                    "paid_traffic_cost": 0,
                    "etv": 6308,
                    "date": "2019-05-16 00:00:00+00:00",
                    "pos1": 7,
                    "pos2_3": 0,
                    "pos4_10": 4,
                    "pos11_20": 10,
                    "pos21_30": 11,
                    "pos31_40": 16,
                    "pos41_50": 17,
                    "pos51_60": 21,
                    "pos61_70": 18,
                    "pos71_80": 18,
                    "pos81_90": 18,
                    "pos91_100": 21,
                    "paid_pos1": 0,
                    "paid_pos2_3": 0,
                    "paid_pos4_10": 0,
                    "paid_pos11_20": 0,
                    "paid_pos21_100": 0
                },
                {
                    "category": [
                        10169
                    ],
                    "country_code": "GB",
                    "language": "en",
                    "organic_count": 98,
                    "paid_count": 0,
                    "organic_traffic_cost": 19012.519,
                    "paid_traffic_cost": 0,
                    "etv": 9801,
                    "date": "2019-05-16 00:00:00+00:00",
                    "pos1": 1,
                    "pos2_3": 0,
                    "pos4_10": 5,
                    "pos11_20": 8,
                    "pos21_30": 13,
                    "pos31_40": 11,
                    "pos41_50": 4,
                    "pos51_60": 8,
                    "pos61_70": 13,
                    "pos71_80": 11,
                    "pos81_90": 14,
                    "pos91_100": 10,
                    "paid_pos1": 0,
                    "paid_pos2_3": 0,
                    "paid_pos4_10": 0,
                    "paid_pos11_20": 0,
                    "paid_pos21_100": 0
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
country_code string ISO country code
required field
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
language string language
required field
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in the List of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
if you don’t specify a language, the results will be returned for all languages
domain string domain
required field
a domain should be specified without http://, https:// and www
type string SERP type
can have the following values: organic, paid
default value: organic
full_tuple boolean ranked keywords categories
If full_tuple: true, you will get data based on the full list of categories. By default, the value is false which means you will get the root category data only.
limit integer maximum number of returned results
optional field
default value: 100
maximum value: 1000
offset integer offset in results array of returned keys
default value: 0
orderby string sorting of results
possible fields that can be used to sort results:
organic_count, paid_count, organic_traffic_cost, paid_traffic_cost, etv, pos1, pos2_3, pos4_10, pos11_20, pos21_30, pos31_40, pos41_50, pos51_60, pos61_70, pos71_80, pos81_90, pos91_100, paid_pos1, paid_pos2_3, paid_pos4_10, paid_pos11_20, paid_pos21_100
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
organic_count,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
organic_count,desc;etv,desc
the following rule is applied by default:
etv,desc
filters array array with filters
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["pos1", ">", 0]
[["etv", ">", 0], "and", ["pos1", "in", [10,20]]]
[["etv", ">", 1000], "and", [["pos1", ">", 0], "and", ["organic_count", ">", 30]]]
      $field string the name of the filtered field
posible filtration parameters:
organic_count, paid_count, organic_traffic_cost, paid_traffic_cost, pos1, pos2_3, pos4_10, pos11_20, pos21_30, pos31_40, pos41_50, pos51_60, pos61_70, pos71_80, pos81_90, pos91_100, paid_pos1, paid_pos2_3, paid_pos4_10, paid_pos11_20, paid_pos21_100, etv
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
<, <=, >, >=, =, <>:     integer
in, not_in:                       array

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            domain string specified domain
            limit integer specified maximum number of returned results
            offset integer offset in results array of returned keys
            orderby string specified sorting of results
            type string specified SERP type
            total_count integer total amount of results in our database by a specific request
            result_count integer number of elements in categories array by a specific request
      categories array result array
            category array product and service categories
you can download the full list of possible categories
            country_code string specified country code
            language string specified language
            organic_count integer number of organic results in SERP
            paid_count integer number of paid results in SERP
            organic_trafic_cost float the value is calculated as ETV*CPC for organic resuls
            paid_trafic_cost float the value is calculated as ETV*CPC for paid resuls
            etv integer estimated traffic to domain based on organic and paid SERP data in system
            date string date update
            pos1 integer number of organic SERP which contain domain at the first place
            pos2_3 integer number of organic SERP which contain domain at the second and third place
            pos4_10 integer number of organic SERP which contain domain at the 4-10 place
            pos11_20 integer number of organic SERP which contain domain at the 11-20 place
            pos21_30 integer number of organic SERP which contain domain at the 21-30 place
            pos31_40 integer number of organic SERP which contain domain at the 31-40 place
            pos41_50 integer number of organic SERP which contain domain at the 41-50 place
            pos51_60 integer number of organic SERP which contain domain at the 51-60 place
            pos61_70 integer number of organic SERP which contain domain at the 61-70 place
            pos71_80 integer number of organic SERP which contain domain at the 71-80 place
            pos81_90 integer number of organic SERP which contain domain at the 81-90 place
            pos91_100 integer number of organic SERP which contain domain at the 91-100 place
            paid_pos1 integer number of paid SERP which contain domain at the first place
            paid_pos2_3 integer number of paid SERP which contain domain at the second and third place
            paid_pos4_10 integer number of paid SERP which contain domain at the 4-10 place
            paid_pos11_20 integer number of paid SERP which contain domain at the 11-20 place
            paid_pos21_100 integer number of paid SERP which contain domain at the 21-100 place

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Keywords For Categories

Using this option, you can get keywords for specified categories.

Get Keywords For Categories

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "categories" => array(12193, 12191),
        "country_code" => "US",
        "language" => "en",
        "limit" => 10
    );

    $get_result = $client->post("v2/kwrd_finder_keywords_for_category", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

$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

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(
    categories==[
        12193,
        12191
    ],
    country_code="US",
    language="en",
    limit=10
)

response = client.post("/v2/kwrd_finder_keywords_for_category", 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.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_finder_keywords_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"))) }
            };
            var rnd = new Random();
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    categories = new[]
                    {
                        12193,
                        12191
                    },
                    country_code = "US",
                    language = "en",
                    limit = 10
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_finder_keywords_for_category", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            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_finder_keywords_for_category() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_keywords_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<>();

        Random rnd = new Random();
        Map<String, Object> postObj = new HashMap<>();
        postObj.put("categories", new Object[]{
            12193,
            12191
        });
        postObj.put("country_code", "US");
        postObj.put("language", "en");
        postObj.put("limit", 10);
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.4121 sec.",
    "results_count": 1,
    "results": {
        "25113049": {
            "post_id": "25113049",
            "task_id": 1258444,
            "meta": {
                "categories": [
                    12193,
                    12191
                ],
                "country_code": "US",
                "language": "en",
                "limit": 10,
                "offset": 0,
                "orderby": "search_volume,desc",
                "total_count": 1026,
                "result_count": 10
            },
            "similar": [
                {
                    "key": "computing",
                    "date": "2019-05-20",
                    "search_volume": 301000,
                    "competition": 0.9997535909226722,
                    "cpc": 1.526451,
                    "history": [
                        {
                            "month": 3,
                            "year": 2019,
                            "search_volume": 301000
                        },
                        {
                            "month": 2,
                            "year": 2019,
                            "search_volume": 301000
                        },
                        {
                            "month": 1,
                            "year": 2019,
                            "search_volume": 368000
                        },
                        {
                            "month": 12,
                            "year": 2018,
                            "search_volume": 368000
                        },
                        {
                            "month": 11,
                            "year": 2018,
                            "search_volume": 450000
                        },
                        {
                            "month": 10,
                            "year": 2018,
                            "search_volume": 368000
                        },
                        {
                            "month": 9,
                            "year": 2018,
                            "search_volume": 368000
                        },
                        {
                            "month": 8,
                            "year": 2018,
                            "search_volume": 368000
                        },
                        {
                            "month": 7,
                            "year": 2018,
                            "search_volume": 301000
                        },
                        {
                            "month": 6,
                            "year": 2018,
                            "search_volume": 301000
                        },
                        {
                            "month": 5,
                            "year": 2018,
                            "search_volume": 301000
                        },
                        {
                            "month": 4,
                            "year": 2018,
                            "search_volume": 301000
                        }
                    ],
                    "categories": [
                        10019,
                        10168,
                        10883,
                        12187,
                        12191,
                        12193
                    ]
                },
                {
                    "key": "dell optiplex",
                    "date": "2019-05-23",
                    "search_volume": 14800,
                    "competition": 0.9998667066546703,
                    "cpc": 1.538783,
                    "history": [
                        {
                            "month": 3,
                            "year": 2019,
                            "search_volume": 18100
                        },
                        {
                            "month": 2,
                            "year": 2019,
                            "search_volume": 18100
                        },
                        {
                            "month": 1,
                            "year": 2019,
                            "search_volume": 18100
                        },
                        {
                            "month": 12,
                            "year": 2018,
                            "search_volume": 18100
                        },
                        {
                            "month": 11,
                            "year": 2018,
                            "search_volume": 18100
                        },
                        {
                            "month": 10,
                            "year": 2018,
                            "search_volume": 18100
                        },
                        {
                            "month": 9,
                            "year": 2018,
                            "search_volume": 14800
                        },
                        {
                            "month": 8,
                            "year": 2018,
                            "search_volume": 14800
                        },
                        {
                            "month": 7,
                            "year": 2018,
                            "search_volume": 14800
                        },
                        {
                            "month": 6,
                            "year": 2018,
                            "search_volume": 12100
                        },
                        {
                            "month": 5,
                            "year": 2018,
                            "search_volume": 14800
                        },
                        {
                            "month": 4,
                            "year": 2018,
                            "search_volume": 14800
                        }
                    ],
                    "categories": [
                        10019,
                        10168,
                        10883,
                        12187,
                        12191,
                        12193
                    ]
                },
                {
                    "key": "dell optiplex 7010",
                    "date": "2019-05-23",
                    "search_volume": 8100,
                    "competition": 1,
                    "cpc": 0.742031,
                    "history": [
                        {
                            "month": 3,
                            "year": 2019,
                            "search_volume": 8100
                        },
                        {
                            "month": 2,
                            "year": 2019,
                            "search_volume": 8100
                        },
                        {
                            "month": 1,
                            "year": 2019,
                            "search_volume": 9900
                        },
                        {
                            "month": 12,
                            "year": 2018,
                            "search_volume": 8100
                        },
                        {
                            "month": 11,
                            "year": 2018,
                            "search_volume": 8100
                        },
                        {
                            "month": 10,
                            "year": 2018,
                            "search_volume": 8100
                        },
                        {
                            "month": 9,
                            "year": 2018,
                            "search_volume": 6600
                        },
                        {
                            "month": 8,
                            "year": 2018,
                            "search_volume": 6600
                        },
                        {
                            "month": 7,
                            "year": 2018,
                            "search_volume": 6600
                        },
                        {
                            "month": 6,
                            "year": 2018,
                            "search_volume": 6600
                        },
                        {
                            "month": 5,
                            "year": 2018,
                            "search_volume": 6600
                        },
                        {
                            "month": 4,
                            "year": 2018,
                            "search_volume": 6600
                        }
                    ],
                    "categories": [
                        10019,
                        10168,
                        10883,
                        12187,
                        12191,
                        12193
                    ]
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
country_code string ISO country code
required field
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
language string language
required field
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in the List of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
if you don’t specify a language, the results will be returned for all languages
categories array product and service categories
required field
you can download the full list of possible categories
intersections boolean category intersection mode
optional field
If you specify more than one category, you can use the intersection mode.
By default intersections: true, which means that you will get only keywords that appear in each of the specified categories. If you set it to false you will receive all keywords that appear in specified categories, regardless their intersections.
limit integer maximum number of returned results
optional field
default value: 100
maximum value: 1000
offset integer offset in results array of returned keys
optional field
default value: 0
orderby string sorting of results
optional field
possible fields that can be used to sort results:
key, search_volume, competition, cpc
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
competition,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
competition,desc;cpc,desc
the following rule is applied by default:
search_volume,desc
filters array array with filters
optional field
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["search_volume", ">", 0]
[["search_volume", ">", 0], "and", ["search_volume", "in", [10,20]]]
[["cpc", ">", 0], "and", [["search_volume", ">", 0], "and", ["search_volume", "<", 500]]]
      $field string the name of the filtered field
posible filtration parameters:
key, search_volume, competition, cpc
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in, like, not_like
use the following combination of filter fields and comparison operators:
key:
    like, not_like, =, <>
search_volume, competition, cpc:
    <, <=, >, >=, =, <>, in, not_in
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
like, not_like, =, <>:    string
<, <=, >, >=, =, <>:     integer
in, not_in:                       array

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            categories array specified categories
            country_code string specified country code
            language string specified language
            limit integer specified maximum number of returned results
            offset integer offset in results array of returned keys
            orderby string specified sorting of results
            total_count integer total amount of results in our database by a specific request
            result_count integer number of elements in similar array by a specific request
      similar array result array
            key string keyword
keyword for specified category
            date string date update
            search_volume integer average search volume
represents the (approximate) number of searches for the given keyword idea on google.com
            competition float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. Can accept values between 0 and 1 inclusive
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword
            history array searches history
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
            categories array product and service categories
you can download the full list of possible categories

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Ranked Domains By Category

Using this option, you can check what domains are ranked for specific categories.

Get Ranked Domains By Category

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();  
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "categories" => array(13841),
        "country_code" => "GB",
        "language" => "en",
        "limit" => 10,
        "orderby" => "organic_count,desc"
    );

    $get_result = $client->post("v2/kwrd_finder_ranked_domains_by_category_get", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

$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

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(
    categories=[13841],
    country_code="GB",
    language="en",
    limit=10,
    orderby="organic_count,desc"
)

response = client.post("/v2/kwrd_finder_ranked_domains_by_category_get", 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.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_finder_ranked_domains_by_category_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 rnd = new Random();
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    categories = new[]
                    {
                        13841
                    },
                    country_code = "US",
                    language = "en",
                    limit = 10,
                    orderby = "organic_count,desc"
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_finder_ranked_domains_by_category_get", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            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_finder_ranked_domains_by_category_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_ranked_domains_by_category_get");
        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("categories", new Object[]{
            13841
        });
        postObj.put("country_code", "GB");
        postObj.put("language", "en");
        postObj.put("limit", 10);
        postObj.put("orderby", "organic_count,desc");
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.7265 sec.",    
    "results_count": 1,
    "results": {
        "113154235149": {
            "post_id": "113154235149",
            "task_id": 3291258337,
            "meta": {
                "categories": [
                    13841
                ],
                "limit": 10,
                "offset": 0,
                "orderby": "organic_count,desc",
                "type": "organic",
                "total_count": 31726,
                "result_count": 10
            },
            "domains": [
                {
                    "category": 13841,
                    "domain": "indiatimes.com",
                    "country_code": "GB",
                    "language": "en",
                    "organic_count": 4,
                    "paid_count": 0,
                    "organic_traffic_cost": 157760.534941,
                    "paid_traffic_cost": 0,
                    "etv": 85228,
                    "date": "2019-05-23 00:00:00+00:00",
                    "domain_metric": {
                        "organic_count": 870504,
                        "paid_count": 0,
                        "organic_traffic_cost": 8787321.818178,
                        "etv": 9268770,
                        "date": "2019-04-01 00:00:00+00:00",
                        "pos1": 5451,
                        "pos2_3": 15162,
                        "pos4_10": 74164,
                        "pos11_20": 93668,
                        "pos21_30": 86435,
                        "pos31_40": 87517,
                        "pos41_50": 87439,
                        "pos51_60": 87486,
                        "pos61_70": 87673,
                        "pos71_80": 87338,
                        "pos81_90": 85928,
                        "pos91_100": 72243,
                        "paid_pos1": 0,
                        "paid_pos2_3": 0,
                        "paid_pos4_10": 0,
                        "paid_pos11_20": 0,
                        "paid_pos21_100": 0
                    }
                },
                {
                    "category": 13841,
                    "domain": "khanacademy.org",
                    "country_code": "GB",
                    "language": "en",
                    "organic_count": 3,
                    "paid_count": 0,
                    "organic_traffic_cost": 209.997052,
                    "paid_traffic_cost": 0,
                    "etv": 151,
                    "date": "2019-05-23 00:00:00+00:00",
                    "domain_metric": {
                        "organic_count": 292688,
                        "paid_count": 1,
                        "organic_traffic_cost": 1940359.58822,
                        "etv": 2828379,
                        "date": "2019-04-01 00:00:00+00:00",
                        "pos1": 5555,
                        "pos2_3": 11405,
                        "pos4_10": 38827,
                        "pos11_20": 42585,
                        "pos21_30": 28704,
                        "pos31_40": 23617,
                        "pos41_50": 22234,
                        "pos51_60": 22804,
                        "pos61_70": 24175,
                        "pos71_80": 24963,
                        "pos81_90": 25806,
                        "pos91_100": 22013,
                        "paid_pos1": 1,
                        "paid_pos2_3": 0,
                        "paid_pos4_10": 0,
                        "paid_pos11_20": 0,
                        "paid_pos21_100": 0
                    }
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
categories array product and service categories
you can download the full list of possible categories
country_code string ISO country code
required field
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
language string language
required field
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in the List of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
if you don’t specify a language, the results will be returned for all languages
type string SERP type
can have the following values: organic, paid
default value: organic
limit integer maximum number of returned results
optional field
default value: 100
maximum value: 1000
offset integer offset in results array of returned keys
default value: 0
orderby string sorting of results
possible fields that can be used to sort results:
domain,organic_count, paid_count, organic_traffic_cost, paid_traffic_cost, etv
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
organic_count,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
organic_count,desc;etv,desc
the following rule is applied by default:
etv,desc
filters array array with filters
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["organic_count", ">", 0]
[["etv", ">", 0], "and", ["organic_count", "in", [10,20]]]
[["etv", ">", 1000], "and", [["organic_count", ">", 0], "and", ["organic_count", "<", 30]]]
      $field string the name of the filtered field
posible filtration parameters:
domain, organic_count, paid_count, organic_traffic_cost, paid_traffic_cost, etv
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in, like, not_like

use the following combination of filter fields and comparison operators:
domain:
    like, not_like
organic_count, paid_count, organic_traffic_cost, paid_traffic_cost, etv:
    <, <=, >, >=, =, <>, in, not_in

If you want to filter the results array by the key value using like or not_like operators, you can use the following parameters:
["key", "like", "seo%"]      any values that start with “seo”
["key", "like", "%seo"]      any values that end with “seo”
["key", "like", "%seo%"]    any values that contain “seo”
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
<, <=, >, >=, =, <>:       integer
in, not_in:                       array
like, not_like:                string

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            categories array specified categories
            limit integer specified maximum number of returned results
            offset integer offset in results array of returned keys
            orderby string specified sorting of results
            type string specified SERP type
            total_count integer total amount of results in our database by a specific request
            result_count integer number of elements in categories array by a specific request
      domains array result array
            category string specified category
            domain string domain
            country_code string specified country code
            language string specified language
            organic_count integer number of organic results in SERP for a specific category
            paid_count integer number of paid results in SERP for a specific category
            organic_trafic_cost float the value is calculated as ETV*CPC for organic resuls for a specific category
            paid_trafic_cost float the value is calculated as ETV*CPC for paid resuls for a specific category
            etv integer estimated traffic to domain based on organic and paid SERP data in system for a specific category
            date string current date
            domain_metric array domain metric
                  organic_count integer total number of organic results in SERP for a specific category
                  paid_count integer total number of paid results in SERP for a specific category
                  organic_trafic_cost float the value is calculated as ETV*CPC for total organic resuls
                  paid_trafic_cost float the value is calculated as ETV*CPC for total paid resuls
                  etv integer total estimated traffic to domain based on organic and paid SERP data in system
                  date string date update
                  pos1 integer number of organic SERP which contain domain at the first place
                  pos2_3 integer number of organic SERP which contain domain at the second and third place
                  pos4_10 integer number of organic SERP which contain domain at the 4-10 place
                  pos11_20 integer number of organic SERP which contain domain at the 11-20 place
                  pos21_30 integer number of organic SERP which contain domain at the 21-30 place
                  pos31_40 integer number of organic SERP which contain domain at the 31-40 place
                  pos41_50 integer number of organic SERP which contain domain at the 41-50 place
                  pos51_60 integer number of organic SERP which contain domain at the 51-60 place
                  pos61_70 integer number of organic SERP which contain domain at the 61-70 place
                  pos71_80 integer number of organic SERP which contain domain at the 71-80 place
                  pos81_90 integer number of organic SERP which contain domain at the 81-90 place
                  pos91_100 integer number of organic SERP which contain domain at the 91-100 place
                  paid_pos1 integer number of paid SERP which contain domain at the first place
                  paid_pos2_3 integer number of paid SERP which contain domain at the second and third place
                  paid_pos4_10 integer number of paid SERP which contain domain at the 4-10 place
                  paid_pos11_20 integer number of paid SERP which contain domain at the 11-20 place
                  paid_pos21_100 integer number of paid SERP which contain domain at the 21-100 place

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Domain Intersection

Using this method, you will receive keywords that any two domains share in organic search. This method will allow to identify competing domains through keyword intersections, compare intersecting keyword’s rankings of competing domains and access the importance of these keywords through the search volume, competition, and cost-per-click values.

Get Domain Intersection

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

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

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();
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "country_code" => "US",
        "language" => "en",
        "domain1" => "similarweb.com",
        "domain2" => "dataforseo.com",
        "limit" => 3,
        "filters" => array(
            array("domain_1_pos", "<", 10), 
            "and",
            array("relative_url_2", "like", "/pricing%")
        )       
    );

    $get_result = $client->post("v2/kwrd_finder_domain_intersection_get", array('data' => $post_array));
    print_r($get_result);

    //do something with result

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

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

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(

    country_code="US",
    language="en",
    domain1="similarweb.com",
    domain2="dataforseo.com",
    limit=3,
    filters=[
        ["domain_1_pos", "<", 10],
        "and",
        ["relative_url_2", "like", "/pricing%"]
    ]
)

response = client.post("/v2/kwrd_finder_domain_intersection_get", 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.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_finder_domain_intersection_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 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
                {
                    country_code = "US",
                    language = "en",
                    domain1 = "similarweb.com",
                    domain2 = "dataforseo.com",
                    limit = 3,
                    filters = new object[]
                    {
                        new object[] { "domain_1_pos", "<", 10 },
                        "and",
                        new object[] { "relative_url_2", "like", "/pricing%" }
                    }
                }
            };
            var pagePostResponse = await httpClient.PostAsync("v2/kwrd_finder_domain_intersection_get", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await pagePostResponse.Content.ReadAsStringAsync());
            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_finder_domain_intersection_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_domain_intersection_get");
        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("country_code", "US");
        postObj.put("language", "en");
        postObj.put("domain1", "similarweb.com");
        postObj.put("domain2", "dataforseo.com");
        postObj.put("limit", 3);
        postObj.put("filters", new Object[]{
            new Object[]
                {"domain_1_pos", "<", 10},
            "and",
            new Object[]
                {"relative_url_2", "like", "/pricing%"}
        });
        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.9636 sec.",
    "results_count": 1,
    "results": {
        "11913041": {
            "post_id": "11913041",
            "task_id": 20498638,
            "meta": {
                "domain1": "similarweb.com",
                "domain2": "dataforseo.com",
                "country_code": "US",
                "language": "en",
                "limit": 3,
                "offset": 0,
                "orderby": "search_volume,desc",
                "type": "organic",
                "total_count": 7,
                "result_count": 3
            },
            "intersection": [
                {
                    "keyword": "similarweb pricing",
                    "search_volume": 170,
                    "competition": 0.094285,
                    "cpc": 1.60243,
                    "domain_1_pos": 1,
                    "domain_2_pos": 21,
                    "relative_url_1": "/corp/pricing/",
                    "relative_url_2": "/pricing"
                },
                {
                    "keyword": "similarweb price",
                    "search_volume": 170,
                    "competition": 0.094285,
                    "cpc": 1.60243,
                    "domain_1_pos": 1,
                    "domain_2_pos": 19,
                    "relative_url_1": "/corp/pricing/",
                    "relative_url_2": "/pricing"
                },
                {
                    "keyword": "similar web pricing",
                    "search_volume": 170,
                    "competition": 0.094285,
                    "cpc": 1.60243,
                    "domain_1_pos": 1,
                    "domain_2_pos": 29,
                    "relative_url_1": "/corp/pricing/",
                    "relative_url_2": "/pricing"
                }
            ]
        }
    }
}

You can specify the number of results you want to retrieve, filter and sort them.

All POST data should be sent in the JSON format (UTF-8 encoding). The request setting is done using POST method when array of requests is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
domain1 string first domain
required field
a domain should be specified without http:// and www
domain2 string second domain
required field
a domain should be specified without http:// and www
country_code string ISO country code
required field
the list of available locations can be found in the List of Keywords Finder Locations
the code of a location is specified in the country_code field
or in the List of Locations
the code of a location is specified in the loc_country_iso_code field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: US
if you don’t specify a location, the results will be returned for all available locations
language string language
required field
the list of available languages can be found in the List of Keywords Finder Locations
the code of a language is specified in the language field
or in theList of Locations
the code of a language is specified in the kwrd_finder_lang field, in the kwrd_finder: true field you can see if it is available for Keywords Finder API
for example: en
if you don’t specify a language, the results will be returned for all languages
intersection boolean intersection mode
optional field
If you specify intersection: true you will get the keywords for which both domains have results within the same SERP. If you specify intersection:false, you will get only those keywords for which the results are present only for the first domain.
default value: true
type string SERP type
can have the following values: organic, paid
default value: organic
limit integer maximum number of returned keys
default value: 100
maximum value: 1000
offset integer offset in results array of returned keys
default value: 0
maximum value: 50000
orderby string sorting of results
possible fields that can be used to sort results:
keyword,search_volume, competition, cpc, domain_1_pos, domain_2_pos, relative_url_1, relative_url_2
possible sorting types:
asc, desc
use comma to separate the rules, for instance:
competition,asc
you can also sort results by several fields at once (no more than three sorting rules at a time) by using a semicolon to separate the sets of rules, for instance:
search_volume,desc;cpc,desc
the following rule is applied by default:
search_volume,desc
filters array array with filters
if you use a filter, you must also specify the $field, $operator and $value
you can add a few filters at once (8 filters maximum)
you should set a logical operator and, or between conditions, for instance:
["cpc", ">", 0]
[["cpc", ">", 0], "and", ["search_volume", "in", [10,20]]]
[["search_volume", ">", 500], "or", [["cpc", ">", 1], "and", ["cpc", "<", 10]]]
      $field string the name of the filtered field
posible filtration parameters:
keyword,search_volume, competition, cpc, domain_1_pos, domain_2_pos, relative_url_1, relative_url_2
      $operator string comparison operator
possible operator parameters:
<, <=, >, >=, =, <>, in, not_in, like, not_like

use the following combination of filter fields and comparison operators:
keyword,search_volume, competition, cpc, relative_url_1, relative_url_2:
    like, not_like, =, <>
search_volume, competition, cpc, domain_1_pos, domain_2_pos:
    <, <=, >, >=, =, <>, in, not_in
If you want to filter the results array by the keyword value using like or not_like operators, you can use the following parameters:
["keyword", "like", "seo%"]      any values that start with “seo”
["keyword", "like", "%seo"]      any values that end with “seo”
["keyword", "like", "%seo%"]    any values that contain “seo”
      $value integer/string/array comparison value
use the following combination of comparison operators and data types:
like, not_like, =, <>:    string
<, <=, >, >=, =, <>:       integer
in, not_in:                       array

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

Name of a field Type Description
status string general result
“ok” - successful
“error” - error
if status=“error”, then you can see more detailed information in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results array (concurrent requests)
results array results array
      post_id string index in the array received in a POST request
      task_id integer unique task identifier in our system(UInt64)
      meta array options and common task data
            domain1 string specified first domain
            domain2 string specified second domain
            country_code string ISO country code
            language string language
            limit integer maximum number of returned keywords
            offset integer offset in results array of returned keywords
            orderby string sorting of results
            type string SERP type
            total_count integer total amount of results in our database by a specific request
            result_count integer the number of elements in the intersection array by a specific request
      intersection array results array of the intersection array
            keyword string intersecting keyword
            search_volume integer average search volume
represents the (approximate) number of searches for the given keyword idea at google.com
            competition float competition
represents the relative amount of competition associated with the given keyword idea, relative to other keywords. Can accept values between 0 and 1 inclusive
            cpc float cost-per-click
represents the average cost per click (USD) historically paid for the keyword
            domain_1_pos integer position of the first domain in SERP
            domain_2_pos integer position of the second domain in SERP
            relative_url_1 string first relative URL
the first specified domain’s page ranking for the identified intersecting keyword
            relative_url_2 string second relative URL
the second specified domain’s page ranking for the identified intersecting keyword

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
“post data is empty” - specify parameters for request
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

Suggested Keywords

Using this method, you can get a list of suggested keywords that are shown by Google in the drop-down list at the moment a user is typing in his search query in address bar of the Google Chrome browser. By default, letters of English alphabet and numbers (0-9) are being added for your keyword. Therefore, you are getting the full list of all possible variants in which a specified keyword is included.

For instance, for the keyword ice tea our system adds all the letters of Latin alphabet one by one, and after that the same process is being repeated with numbers: ice tea, ice tea a, ice tea b, ice tea cice tea 1, ice tea 2 etc.

As a result, a user gets data like this:

“search_query”: ice tea
“suggestion”: ice tea flavours, ice tea rapper, ice tea south africa, iced tea recipe, ice tea wife

“search_query”: ice tea a
“suggestion”: ice tea actor, ice tea and coco, ice tea and coco baby, ice tea and vodka, ice tea and lemonade

“search_query”: ice tea b
“suggestion”: iced tea brands, ice tea benefits, ice tea business, iced tea bottling process, iced tea brands south africa

“search_query”: ice tea c
“suggestion”: iced tea cocktails, iced tea concentrate, iced tea concentrate south africa, iced tea calories, ice tea container

“search_query”: ice tea 1
“suggestion”: icetea 1.0, icetea 1.3, icetea 1.3 psp, icetea 1.0 free download, icetea 1.3 download

“search_query”: ice tea 2
“suggestion”: ice tea 2l, iced tea 2 quarts, iced tea 21 day fix, iced tea 2016, ice tea 2 go bottle

etc.

Set a task and retrieve results when our system collects them. On average it takes 15-30 minutes to receive results.

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');

    $post_array = array();
    $my_unq_id = mt_rand(0,30000000); //your unique ID. we will return it with all results. you can set your database ID, string, etc.

    $post_array[$my_unq_id] = array(
        "keyword" => "stone",
        "se_id" => 4790       
    );

    $post_result = $client->post('v2/kwrd_finder_suggest_tasks_post', array('data' => $post_array));
    print_r($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

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(
    dict(
        keyword="stone",
        se_id=4790
    )
)
response = client.post("/v2/kwrd_finder_suggest_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.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_finder_suggest_tasks_post()
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://api.dataforseo.com/"),
                //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
                DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("login:password"))) }
            };
            var rnd = new Random();
            var postObject = new Dictionary<int, object>
            {
                [rnd.Next(1, 30000000)] = new
                {
                    keyword = "stone",
                    se_id = 4790
                }
            };
            var taskPostResponse = await httpClient.PostAsync("v2/kwrd_finder_suggest_tasks_post", new StringContent(JsonConvert.SerializeObject(new { data = postObject })));
            var obj = JsonConvert.DeserializeObject<dynamic>(await taskPostResponse.Content.ReadAsStringAsync());
            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_finder_suggest_tasks_post() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_suggest_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("keyword", "stone");
        postObj.put("se_id", 4790);

        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 pagePostResponse = client.execute(post);
        JSONObject taskPostObj = new JSONObject(EntityUtils.toString(pagePostResponse.getEntity()));

        if (taskPostObj.get("status").equals("error") && taskPostObj.isNull("results_count")) {
            System.out.println("error. Code:" + taskPostObj.getJSONObject("error").get("code") + " Message:" + taskPostObj.getJSONObject("error").get("message"));
        } else {
            JSONObject results = taskPostObj.getJSONObject("results");
            Iterator<String> jkeys = results.keys();
            while (jkeys.hasNext()) {
                String key = jkeys.next();
                String status = "";
                if (!results.getJSONObject(key).isNull("status")) {
                    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.0633 sec.",
    "results_count": 1,
    "results": {
        "11913049": {
            "keyword": "stone",
            "post_id": 11913049,            
            "task_id": 7580
        }
    }
}

To set a task, you should specify a keyword. Also, you can add different alphabets or specific symbols from any alphabet.

All POST data should be sent in the JSON format (UTF-8 encoding). The task setting is done using POST method when array of tasks is sent to the data field. Each of the array elements has the following structure:

Name of a field Type Description
keyword string keyword
required field
UTF-8 encoding
all %## will be decoded (plus symbol ‘+’ will be decoded to a space character)
a keyword should be at least 3 characters long
the keywords will be changed to the lowercase format
se_id integer search engine id
optional field, if you specify se_name and se_language
you must choose one of the fields se_id or se_name
the list of available search engines with se_id you can get by separate request List of Search Engines
you must choose a search engine with the word “suggested” included into the “se_name” field
se_name string search engine domain
optional field if you specify se_id
you must choose one of the fields se_id or se_name
the list of available search engines with se_name you can get by separate request List of Search Engines
you must choose a search engine with the word “suggested” included into the “se_name” field
example: “google.com suggested”
se_language string search engine language
optional field if you specify se_id
required field if se_id is not specified
the list of available search engines with se_language you can get by separate request List of Search Engines
example: “English”
language array alphabet symbols
by default, alphabet which letters will be added to a keyword is «en»
you can specify maximum 3 alphabets at once
shortening of languages is based on the ISO 639-1 standard, possible variants of alphabets:
af, sq, sm, ar, az, eu, be, bn, bh, bs, bg, ca, zh-TW, hr, cs, da, nl, en, eo, et, fo, fi, fr, fy, gl, ka, de, el, gu, iw, hi, hu, is, id, ia, ga, it, ja, jw, kn, ko, la, lv, lt, mk, ms, ml, mt, mr, ne, no, nn, oc, fa, pl, pt-BR, pt-PT, pa, ro, ru, gd, sr, si, sk, sl, es, su, sw, sv, tl, ta, te, th, ti, tr, uk, ur, uz, vi, cy, xh, zu
the alphabet you want to specify should be added to the array, for instance:
["en","pl"]
also, by default, additionally to an alphabet, numeric symbols will be added:
1 2 3 4 5 6 7 8 9
if you don’t need numeric symbols to be added, the parameter numbers should have false value
numbers boolean specifies whether the numeric symbols are added to the keyword
by default, numeric characters will be added, to disable it, you must set the parameter to false
symbols array symbols that will be added to a keyword
maximum 30 symbols can be added at once
the symbols you want to add should be specified in the array, for instance:
["a","b","c","d","e"]
if you specify symbols, such parameters as numbers and language will be ignored.
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 Suggested 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. we will set necessary value before sending of a request. for example:
  http://your-server.com/pingscript?taskId=$task_id

As a response of API server you will receive JSON array in the field results where the information relevant to your request will be specified.

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

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
“post data is empty” - specify parameters to set a task
“this task id is used within another function, check the task id” - check if the task_id is relevant to the API you’ve used
“such the task does not exist” - check the task_id of the task
“task id is empty or not valid” - specify the task_id
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.

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_finder_suggest_tasks_get
    $tasks_get_result = $client->get('v2/kwrd_finder_suggest_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_finder_suggest_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_finder_suggest_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_finder_suggest_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_finder_suggest_tasks_get() throws JSONException, IOException, URISyntaxException {
        URI url = new URI("https://api.dataforseo.com/v2/kwrd_finder_suggest_tasks_get");
        HttpClient client;
        client = HttpClientBuilder.create().build();
        HttpGet get = new HttpGet(url);
        //Instead of 'login' and 'password' use your credentials from https://my.dataforseo.com/login
        String basicAuth = Base64.getEncoder().encodeToString(("login:password").getBytes("UTF-8"));

        get.setHeader("Content-type", "application/json");
        get.setHeader("Authorization", "Basic " + basicAuth);
        HttpResponse completedTasksResponse = client.execute(get);
        JSONObject completedTasksObj = new JSONObject(EntityUtils.toString(completedTasksResponse.getEntity()));

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

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0947 sec.",
    "results_count": 4,
    "results": [
        {
            "task_id": 7734,
            "data": true
        },
        {
            "task_id": 7730,
            "data": true
        },
        {
            "task_id": 7706,
            "data": true
        },
        {
            "task_id": 7702,
            "data": true
        }
    ]
}

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.

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 string number of elements in the array of results results
results array results array of tasks
      task_id integer unique task identifier in our system(UInt64)
in the future you will be able to use it within 7 days to request results of this task any time
      data boolean true - the task is completed, you can collect its results
false - the task wasn’t completed due to the error that occured in the process

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');

    $task_id = 473;
    $get_result = $client->get('v2/kwrd_finder_suggest_tasks_get/' . $task_id);
    print_r($get_result);

    //do something with result

} catch (RestClientException $e) {
    echo "\n";
    print "HTTP code: {$e->getHttpCode()}\n";
    print "Error code: {$e->getCode()}\n";
    print "Message: {$e->getMessage()}\n";
    print  $e->getTraceAsString();
    echo "\n";
    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")
task_id = 473
response = client.get("/v2/kwrd_finder_suggest_tasks_get/%s" % (task_id))
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_finder_suggest_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 task_id = 473;
            var kwrdResponse = await httpClient.GetAsync($"v2/kwrd_finder_suggest_tasks_get/{task_id}");
            var kwrdObj = JsonConvert.DeserializeObject<dynamic>(await kwrdResponse.Content.ReadAsStringAsync());
            if (kwrdObj.status == "error")
                Console.WriteLine($"error. Code: {kwrdObj.error.code} Message: {kwrdObj.error.message}");
            foreach (var kwrdResult in kwrdObj.results)
                Console.WriteLine((IEnumerable<dynamic>)kwrdResult);
        }
    }
}
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_finder_suggest_tasks_get_by_task_id() throws JSONException, IOException {
        HttpClient client;
        client = HttpClientBuilder.create().build();
        int taskId = 473;
        HttpGet get = new HttpGet("https://api.dataforseo.com/v2/kwrd_finder_suggest_tasks_get/" + taskId);
        //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 kwrdResponse = client.execute(get);
        JSONObject kwrdObj = new JSONObject(EntityUtils.toString(kwrdResponse.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());
        }
    }
}

The above command returns JSON structured like this:

{
    "status": "ok",
    "results_time": "0.0871 sec.",
    "results_count": 1,
    "keyword": "stone",
    "task_id": 473,
    "parameters": {
        "se_id": 4802,
        "symbols": [
            "a",
            "b",
            "c"
        ]
    },
    "total_count": 78,
    "suggestions": [
        {
            "number": 1,
            "relevance": 1050,
            "search_query": "stone a",
            "suggestion": "stone age"
        },
        {
            "number": 2,
            "relevance": 602,
            "search_query": "stone a",
            "suggestion": "stone and strand"
        },
        {
            "number": 3,
            "relevance": 600,
            "search_query": "stone a",
            "suggestion": "stone arch bridge"
        },
        {
            "number": 20,
            "relevance": 700,
            "search_query": "stone b",
            "suggestion": "stone brewery"
        },
        {
            "number": 21,
            "relevance": 601,
            "search_query": "stone b",
            "suggestion": "stone bridge"
        },
        {
            "number": 39,
            "relevance": 1250,
            "search_query": "stone",
            "suggestion": "= 6.35029318 kilograms"
        },
        {
            "number": 61,
            "relevance": 750,
            "search_query": "stone c",
            "suggestion": "stone cold lyrics"
        },
        {
            "number": 62,
            "relevance": 602,
            "search_query": "stone c",
            "suggestion": "stone crab"
        },
        {
            "number": 63,
            "relevance": 600,
            "search_query": "stone c",
            "suggestion": "stone creek"
        }
    ]
}

To get collected results, specify its task_id.

As a response of API server you will receive array in the field suggestionsof 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 in the error array
error array informational array of error
only if status=“error”
      code integer error code
      message string text description of the error
results_time string execution time, seconds
results_count integer number of elements in the results
keyword string keyword received in a POST array
keyword is returned decoded %## (plus symbol ‘+’ is decoded as a space character)
task_id integer unique task identifier in our system(UInt64)
in the future you will be able to use it within 7 days to request results of this task any time
parameters array task parameters
total_count integer number of elements in the suggestions array
suggestions array results array of suggestions
      number integer number in the list
      relevance integer relevancy of a keyword from search_query field
as a rule, the range is 500-2000, the higher the value is, the more relevant keyword from result array is
      search_query string generated search query
      suggestion string suggested keyword
keyword suggested by Google for the search_query request

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
“post data is empty” - specify parameters to set a task
“this task id is used within another function, check the task id” - check if the task_id is relevant to the API you’ve used
“such the task does not exist” - check the task_id of the task
“task id is empty or not valid” - specify the task_id
500 “init error, please contact support” - some internal error.
if you see this type of error please contact our support team.
We did our best to avoid this type of error.