cURL
curl --request POST \
--url https://api.brightdata.com/zone \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"zone": {
"name": "zone-name",
"type": "serp"
},
"plan": {
"type": "unblocker",
"serp": true,
"country": "any",
"solve_captcha_disable": true,
"custom_headers": false
}
}
'import requests
url = "https://api.brightdata.com/zone"
payload = {
"zone": {
"name": "zone-name",
"type": "serp"
},
"plan": {
"type": "unblocker",
"serp": True,
"country": "any",
"solve_captcha_disable": True,
"custom_headers": False
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
zone: {name: 'zone-name', type: 'serp'},
plan: {
type: 'unblocker',
serp: true,
country: 'any',
solve_captcha_disable: true,
custom_headers: false
}
})
};
fetch('https://api.brightdata.com/zone', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.brightdata.com/zone",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'zone' => [
'name' => 'zone-name',
'type' => 'serp'
],
'plan' => [
'type' => 'unblocker',
'serp' => true,
'country' => 'any',
'solve_captcha_disable' => true,
'custom_headers' => false
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.brightdata.com/zone"
payload := strings.NewReader("{\n \"zone\": {\n \"name\": \"zone-name\",\n \"type\": \"serp\"\n },\n \"plan\": {\n \"type\": \"unblocker\",\n \"serp\": true,\n \"country\": \"any\",\n \"solve_captcha_disable\": true,\n \"custom_headers\": false\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.brightdata.com/zone")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"zone\": {\n \"name\": \"zone-name\",\n \"type\": \"serp\"\n },\n \"plan\": {\n \"type\": \"unblocker\",\n \"serp\": true,\n \"country\": \"any\",\n \"solve_captcha_disable\": true,\n \"custom_headers\": false\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.brightdata.com/zone")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"zone\": {\n \"name\": \"zone-name\",\n \"type\": \"serp\"\n },\n \"plan\": {\n \"type\": \"unblocker\",\n \"serp\": true,\n \"country\": \"any\",\n \"solve_captcha_disable\": true,\n \"custom_headers\": false\n }\n}"
response = http.request(request)
puts response.read_bodyZones
Add a zone
Use the Bright Data Account Management API to add a Zone. POST /zone returns 200 OK with zone or account configuration data as JSON.
POST
/
zone
cURL
curl --request POST \
--url https://api.brightdata.com/zone \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"zone": {
"name": "zone-name",
"type": "serp"
},
"plan": {
"type": "unblocker",
"serp": true,
"country": "any",
"solve_captcha_disable": true,
"custom_headers": false
}
}
'import requests
url = "https://api.brightdata.com/zone"
payload = {
"zone": {
"name": "zone-name",
"type": "serp"
},
"plan": {
"type": "unblocker",
"serp": True,
"country": "any",
"solve_captcha_disable": True,
"custom_headers": False
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
zone: {name: 'zone-name', type: 'serp'},
plan: {
type: 'unblocker',
serp: true,
country: 'any',
solve_captcha_disable: true,
custom_headers: false
}
})
};
fetch('https://api.brightdata.com/zone', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.brightdata.com/zone",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'zone' => [
'name' => 'zone-name',
'type' => 'serp'
],
'plan' => [
'type' => 'unblocker',
'serp' => true,
'country' => 'any',
'solve_captcha_disable' => true,
'custom_headers' => false
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.brightdata.com/zone"
payload := strings.NewReader("{\n \"zone\": {\n \"name\": \"zone-name\",\n \"type\": \"serp\"\n },\n \"plan\": {\n \"type\": \"unblocker\",\n \"serp\": true,\n \"country\": \"any\",\n \"solve_captcha_disable\": true,\n \"custom_headers\": false\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.brightdata.com/zone")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"zone\": {\n \"name\": \"zone-name\",\n \"type\": \"serp\"\n },\n \"plan\": {\n \"type\": \"unblocker\",\n \"serp\": true,\n \"country\": \"any\",\n \"solve_captcha_disable\": true,\n \"custom_headers\": false\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.brightdata.com/zone")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"zone\": {\n \"name\": \"zone-name\",\n \"type\": \"serp\"\n },\n \"plan\": {\n \"type\": \"unblocker\",\n \"serp\": true,\n \"country\": \"any\",\n \"solve_captcha_disable\": true,\n \"custom_headers\": false\n }\n}"
response = http.request(request)
puts response.read_bodyOnly users with Admin or Ops roles can perform this action.
This API can modify your account settings, damage your operations or incur charges.
Paste your API key to the authorization field. To get an API key, Create an account and learn how to generate an API key
ISP proxy zone examples
Creating an ISP zone requires specific parameter combinations. The fields below are not optional. Omitting them will silently create the wrong zone type or billing plan.Setting
zone.type to ISP alone will create a Datacenter zone, not an ISP zone. You must also set plan.pool_ip_type to static_res. Country codes must be lowercase (e.g. us, gb). Uppercase codes return a misleading “no IPs available” error.Shared ISP (pay-per-GB)
{
"zone": { "name": "my_isp_zone", "type": "ISP" },
"plan": {
"type": "static",
"pool_ip_type": "static_res",
"ips_type": "shared",
"bandwidth": "bandwidth",
"country": "us"
}
}
Shared ISP (unlimited bandwidth)
Settingbandwidth: unlimited alone does not activate unlimited billing. You must also include unl_bw_tiers: std.
{
"zone": { "name": "my_isp_zone", "type": "ISP" },
"plan": {
"type": "static",
"pool_ip_type": "static_res",
"ips_type": "shared",
"bandwidth": "unlimited",
"unl_bw_tiers": "std",
"country": "us"
}
}
Dedicated ISP (unlimited bandwidth)
{
"zone": { "name": "my_isp_zone", "type": "ISP" },
"plan": {
"type": "static",
"pool_ip_type": "static_res",
"ips_type": "dedicated",
"bandwidth": "unlimited",
"unl_bw_tiers": "std",
"country": "us",
"ips": 10
}
}
Residential proxy zone
New Residential zones require KYC approval. For Residential zones created after July 7, 2026, adding a zone is available only to KYC-verified companies. A request from an account that has not completed KYC is blocked and returns HTTP 403 with a compliance error. Residential zones created on or before July 7, 2026 are unaffected and continue to work as expected. Start at KYC verification and see the Residential network access policy.
Dedicated Residential (gIP) zone
A dedicated Residential zone allocates a gIP (group of IPs) that is exclusive to a fixed list of target domains. Create one by settingvips_type: "domain" and including domain_whitelist.
Dedicated Residential gIPs are domain-restricted. You must set
vips_type: "domain" and include domain_whitelist (a space-separated list of target domains). vip_country applies only to dedicated zones. For a shared zone, set the country with the -country username flag instead. Country codes must be lowercase (e.g. us, gb).example.com. This payload was verified working on July 9, 2026.
{
"zone": { "name": "my_dedicated_resi_zone", "type": "resident" },
"plan": {
"type": "resident",
"vips_type": "domain",
"vips": 1,
"vip_country": "us",
"domain_whitelist": "example.com"
}
}
domain_whitelist. Requests to any other domain are routed through Bright Data’s shared Datacenter proxies.
Shared Residential country targeting
For shared Residential zones, country is not set withvip_country. Target countries at request level with the -country-<code> flag in the proxy username (for example -country-us), or set default countries in the control panel. See How to configure your Residential proxy.
Dedicated Residential gIP errors
An invalid dedicated Residential (gIP) payload returns one of the following errors.| Error | Cause | How to fix |
|---|---|---|
Can't allocate required amount of gIPs. Dedicated gIPs are only supported with "vips_type": "domain" together with a "domain_whitelist" | Wrong vips_type value | Set vips_type: "domain" |
Can't allocate required amount of gIPs. Target domains ("domain_whitelist") are required to allocate dedicated gIPs | Missing domain_whitelist | Add domain_whitelist with your target domain(s) |
Residential 403 compliance errors
For Residential zones created after July 7, 2026, an Add-a-Zone request from an account that is not eligible returns HTTP 403 with one of the following compliance errors. Zones created on or before July 7, 2026 are not affected. See the proxy errors catalog for the full catalog.| Error code | When it fires | How to fix |
|---|---|---|
kyc_required | A company-email account that has not completed KYC. | Start KYC verification. A human compliance reviewer approves Residential access. |
business_account_required | A personal-email account (not a verified company). | Use a corporate email and contact the Bright Data team to establish business eligibility. Personal-email accounts are not eligible for Residential. |
code value. A company-email account without KYC receives kyc_required:
{
"error": {
"code": "kyc_required",
"message": "Residential proxies are available to verified companies only, after KYC review, in accordance with Bright Data's compliance policy.",
"action": "Start verification at brightdata.com/cp/kyc. Applications are reviewed by our compliance team.",
"alternatives": [
{ "product": "ISP proxy", "plan": { "type": "static", "pool_ip_type": "static_res", "ips_type": "shared" } },
{ "product": "Web Unlocker API", "plan": { "type": "unblocker" } }
],
"docs": "https://docs.brightdata.com/compliance/kyc"
}
}
business_account_required, which does not offer KYC because personal accounts are not eligible:
{
"error": {
"code": "business_account_required",
"message": "Residential proxies are available to verified companies only. Eligibility requires a corporate email and full verification with the Bright Data team.",
"action": "Contact the Bright Data team with a corporate email to determine business eligibility for Residential access.",
"alternatives": [
{ "product": "ISP proxy", "plan": { "type": "static", "pool_ip_type": "static_res", "ips_type": "shared" } },
{ "product": "Web Unlocker API", "plan": { "type": "unblocker" } }
],
"docs": "https://docs.brightdata.com/compliance/kyc"
}
}
alternatives array with the exact plan objects to create a no-KYC ISP or Web Unlocker API zone instead. To create the ISP zone, send POST /zone with that plan object in place of the Residential one.Authorizations
Use your Bright Data API Key as a Bearer token in the Authorization header.
How to authenticate:
- Obtain your API Key from the Bright Data account settings at https://brightdata.com/cp/setting/users
- Include the API Key in the Authorization header of your requests
- Format:
Authorization: Bearer YOUR_API_KEY
Example:
Authorization: Bearer b5648e1096c6442f60a6c4bbbe73f8d2234d3d8324554bd6a7ec8f3f251f07df
Learn how to get your Bright Data API key: https://docs.brightdata.com/api-reference/authentication
Body
application/json
Show child attributes
Show child attributes
Example:
{ "name": "zone-name", "type": "serp" }
Creates a SERP API zone for scraping search engine results.
- SERP API
- Scraping Browser
- Residential Proxy
- Mobile Proxy
- ISP Proxy – Shared (Pay-per-GB)
- ISP Proxy – Shared (Unlimited Bandwidth)
- ISP Proxy – Dedicated
- Datacenter Proxy – Shared
- Datacenter Proxy – Dedicated
Show child attributes
Show child attributes
Response
201
Zone added
Was this page helpful?