Repository files navigation

sdk-banner(1)

Bright Data JavaScript SDK providing easy and scalable methods for scraping, web search, datasets, and more.

Installation @latest

npm install @brightdata/sdk

Quick start

1. Signup and get your API token

2. Initialize the client

import{bdclient}from'@brightdata/sdk';constclient=newbdclient({apiKey: '[your_api_token]',// or set BRIGHTDATA_API_TOKEN env variable});

3. Launch your first request

// Scrape a webpageconsthtml=awaitclient.scrapeUrl('https://example.com');console.log(html);// Search the webconstresults=awaitclient.search.google('pizza restaurants',{country: 'us'});console.log(results);

Don't forget to close when done:

awaitclient.close();

Features

  • Web Scraping — Scrape any website using anti-bot detection bypass and proxy support
  • Search Engine Results — Google, Bing, and Yandex search with batch support
  • Platform Scrapers — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
  • Crawl API — Crawl any URL(s) and get every output format (markdown, HTML, text) bundled per page
  • Discover API — AI-powered web search with intent-based relevance ranking
  • Scraper Studio — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
  • Browser API — CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers
  • Datasets — Access 126 pre-built datasets across dozens of platforms with query/download support
  • Parallel Processing — Concurrent processing for multiple URLs or queries
  • Robust Error Handling — Typed error classes with retry logic
  • Zone Management — Automatic zone creation and management
  • Multiple Output Formats — HTML, JSON, Markdown, and screenshots
  • Dual Build — Both ESM and CommonJS supported
  • TypeScript — Fully typed API with overloaded signatures
  • Subpath Exports — Tree-shakeable imports via @brightdata/sdk/scrapers, @brightdata/sdk/search, @brightdata/sdk/datasets

Usage

Scrape websites

// Single URL — returns HTML string by defaultconsthtml=awaitclient.scrapeUrl('https://example.com');// Multiple URLs (parallel processing)constresults=awaitclient.scrapeUrl(['https://example1.com','https://example2.com',]);// Get markdown contentconstmd=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'markdown',});// Get structured JSONconstdata=awaitclient.scrapeUrl('https://example.com',{format: 'json',});// Take a screenshotconstscreenshot=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'screenshot',});// Full optionsconstresult=awaitclient.scrapeUrl('https://example.com',{format: 'raw',// 'raw' (default) or 'json'dataFormat: 'html',// 'html' (default), 'markdown' (alias: 'md'), 'screenshot'country: 'gb',// two-letter country codemethod: 'GET',// HTTP method});

Search engines

// Google searchconstresults=awaitclient.search.google('pizza restaurants');// Bing searchconstresults=awaitclient.search.bing('pizza restaurants');// Yandex searchconstresults=awaitclient.search.yandex('pizza restaurants');// Batch search (parallel)constresults=awaitclient.search.google(['pizza','sushi','tacos']);// With optionsconstresults=awaitclient.search.google('pizza',{country: 'gb',format: 'json',});

Note: If country is not specified, requests exit through an arbitrary proxy location, so results may be geo-located to an unexpected country. Always pass country when you need consistent, localized results.

Platform scrapers

Collect structured data from popular platforms. Each platform supports sync collection (collect*) and async orchestrated scraping (trigger, poll, download).

// LinkedIn profilesconstdata=awaitclient.scrape.linkedin.collectProfiles(['https://www.linkedin.com/in/satyanadella/'],{format: 'json'},);// Amazon productsconstdata=awaitclient.scrape.amazon.collectProducts(['https://www.amazon.com/dp/B0D77BX8Y4'],{format: 'json'},);// Instagram profilesconstdata=awaitclient.scrape.instagram.collectProfiles(['https://www.instagram.com/natgeo/'],{format: 'json'},);// TikTok profilesconstdata=awaitclient.scrape.tiktok.collectProfiles(['https://www.tiktok.com/@tiktok'],{format: 'json'},);// YouTube videosconstdata=awaitclient.scrape.youtube.collectVideos(['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],{format: 'json'},);// Reddit postsconstdata=awaitclient.scrape.reddit.collectPosts(['https://www.reddit.com/r/technology/top/'],{format: 'json'},);

Orchestrated scraping (async trigger → poll → download):

constresult=awaitclient.scrape.linkedin.profiles(['https://www.linkedin.com/in/satyanadella/'],{pollInterval: 5000,pollTimeout: 180_000},);console.log(result.data);// structured dataconsole.log(result.status);// 'ready'console.log(result.rowCount);

Available platforms:linkedin, amazon, instagram, tiktok, youtube, reddit, facebook, pinterest, chatGPT, digikey, perplexity

Crawl API

Crawl one or more URLs and get every output format (markdown, HTML, text) bundled per page.

// Sync — single round-tripconstresult=awaitclient.crawler.crawl('https://example.com');console.log(result.data[0].markdown);// Batchconstresult=awaitclient.crawler.crawl(['https://example.com','https://example.com/about',]);console.log(`${result.pageCount} pages`);// Async — trigger, poll, downloadconstjob=awaitclient.crawler.trigger('https://example.com');conststatus=awaitclient.crawler.status(job.snapshotId);constresult=awaitclient.crawler.download(job.snapshotId);

Discover API

AI-powered web search with relevance ranking based on intent.

discover() resolves to a DiscoverResult wrapper (not a bare array). The items are on result.data (or its alias result.results), and the result is iterable. On failure result.success is false, result.error carries the reason, and result.data / result.results stay an empty array — so iterating never throws.

// Basic searchconstresult=awaitclient.discover('artificial intelligence trends 2026');if(!result.success){console.error('discover failed:',result.error);}else{console.log(result.results);// [{ link, title, description, relevance_score }, ...]for(constitemofresult){console.log(`[${item.relevance_score}] ${item.title}`);}}// With intent for semantic rankingconstresult=awaitclient.discover('Tesla battery technology',{intent: 'recent breakthroughs in EV battery chemistry',});// With filtering and localizationconstresult=awaitclient.discover('sustainable fashion brands',{intent: 'eco-friendly clothing companies',filterKeywords: ['sustainability','eco-friendly','organic'],country: 'us',numResults: 10,});// Include full page contentconstresult=awaitclient.discover('python asyncio tutorial',{includeContent: true,numResults: 3,});// Manual trigger/poll/fetchconstjob=awaitclient.discoverTrigger('market research SaaS',{intent: 'competitor pricing strategies',});awaitjob.wait({timeout: 60_000});constdata=awaitjob.fetch();

Scraper Studio

Trigger and fetch results from your custom scrapers built in Scraper Studio.

// Orchestrated — trigger + poll + return resultsconstresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: {url: 'https://example.com/product/1'},});// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }// Multiple inputs (processed sequentially)constresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: [{url: 'https://example.com/product/1'},{url: 'https://example.com/product/2'},],});// Manual control — trigger, then poll yourselfconstjob=awaitclient.scraperStudio.trigger('c_your_collector_id',{url: 'https://example.com/product/1',});constdata=awaitjob.waitAndFetch();// Check job status (by job ID from the dashboard)conststatus=awaitclient.scraperStudio.status('j_abc123');console.log(status.status);// 'queued' | 'running' | 'done' | 'failed'

Browser API

Build CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers. Credentials come from browserUsername/browserPassword options or BRIGHTDATA_BROWSERAPI_USERNAME/BRIGHTDATA_BROWSERAPI_PASSWORD env vars.

// Get a connection URLconsturl=client.browser.getConnectUrl();// Geo-target the browser with a 2-letter country codeconstusUrl=client.browser.getConnectUrl({country: 'us'});// Connect with Playwrightimport{chromium}from'playwright';constbrowser=awaitchromium.connectOverCDP(url);constpage=awaitbrowser.newPage();awaitpage.goto('https://example.com');consthtml=awaitpage.content();awaitbrowser.close();

Datasets

Access 126 pre-built datasets for querying and downloading structured data snapshots.

constds=client.datasets;// List all datasets available on your accountconstlist=awaitds.list();// Get field metadata for a datasetconstmeta=awaitds.instagramProfiles.getMetadata();console.log(meta.fields);// [{ name, type, description }, ...]// Query a dataset (triggers a snapshot)constsnapshotId=awaitds.instagramProfiles.query({url: 'https://www.instagram.com/natgeo/'},{records_limit: 10},);// Check snapshot statusconststatus=awaitds.instagramProfiles.getStatus(snapshotId);console.log(status.status);// 'running' | 'ready' | ...// Download when readyconstrows=awaitds.instagramProfiles.download(snapshotId);

Available datasets:

PlatformDatasets
LinkedInlinkedinProfiles, linkedinCompanies
AmazonamazonProducts, amazonReviews, amazonSellers, amazonBestSellers, amazonProductsSearch, amazonProductsGlobal, amazonWalmart
InstagraminstagramProfiles, instagramPosts, instagramComments, instagramReels
TikToktiktokProfiles, tiktokPosts, tiktokComments, tiktokShop
X/TwitterxTwitterPosts, xTwitterProfiles

Saving results

constdata=awaitclient.scrapeUrl('https://example.com');constfilePath=awaitclient.saveResults(data,{filename: 'results.json',format: 'json',});console.log(`Saved to: ${filePath}`);

Configuration

Runtime support

Node.js (>= 20) is the supported and tested runtime. The SDK also runs under Bun without crashing, but with a real caveat: Bun's bundled undici provides only a bare-bones Agent (no compose(), no close(), no custom dispatch), and Bun's request()/stream() ignore the dispatcher option entirely, routing through Bun's own native HTTP client instead. In practice this means requests still succeed under Bun, but none of Transport's tuning — connection pooling, keep-alive, custom timeouts, automatic retry on 429/500/502/503/504, and DNS caching — has any effect there; Bun's own defaults apply instead. The SDK detects the missing capabilities automatically (never crashes construction or close()), rather than failing.

API Token

Get your API token from Bright Data Control Panel.

Already logged in with the CLI? The SDK works with no configuration. If you've run brightdata login with the Bright Data CLI, the SDK automatically picks up those stored credentials. The token is resolved in this order:

  1. apiKey passed to new bdclient({ apiKey })
  2. BRIGHTDATA_API_TOKEN (or BRIGHTDATA_API_KEY) environment variable
  3. Credentials stored by the CLI (brightdata login)

If none are found, the client throws with instructions to log in or set a token.

Environment Variables

BRIGHTDATA_API_TOKEN=your_api_token# BRIGHTDATA_API_KEY also acceptedBRIGHTDATA_WEB_UNLOCKER_ZONE=your_web_unlocker_zone# OptionalBRIGHTDATA_SERP_ZONE=your_serp_zone# OptionalBRIGHTDATA_BROWSERAPI_USERNAME=your_browser_username# Optional, for Browser APIBRIGHTDATA_BROWSERAPI_PASSWORD=your_browser_password# Optional, for Browser APIBRIGHTDATA_VERBOSE=1# Optional, enable verbose logging

Tip: When loading these from a .env file with node --env-file=.env, note that variables already set in your shell take precedence over the file.

Client Options

constclient=newbdclient({apiKey: 'string',// API token (or use BRIGHTDATA_API_TOKEN env var)timeout: 120000,// Request timeout in ms (1000–300000)autoCreateZones: true,// Auto-create zones if they don't existwebUnlockerZone: 'string',// Custom web unlocker zone nameserpZone: 'string',// Custom SERP zone namelogLevel: 'INFO',// 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'structuredLogging: true,// Use structured JSON loggingverbose: false,// Enable verbose loggingrateLimit: 0,// Max requests per period (0 = unlimited)ratePeriod: 1000,// Rate limit period in ms});

Resource Cleanup

The client maintains HTTP connections. Always close when done:

awaitclient.close();// Or use Symbol.asyncDispose (TypeScript 5.2+)awaitusingclient=newbdclient();

Constants

ConstantDefaultDescription
DEFAULT_CONCURRENCY10Max parallel tasks
DEFAULT_TIMEOUT120000Request timeout (milliseconds)
MAX_RETRIES3Retry attempts on failure
RETRY_BACKOFF_FACTOR1.5Exponential backoff multiplier

Zone Management

constzones=awaitclient.listZones();console.log(`Found ${zones.length} zones`);

Subpath Exports

For tree-shaking or importing only what you need:

import{ScrapeRouter,LinkedinAPI}from'@brightdata/sdk/scrapers';import{SearchRouter}from'@brightdata/sdk/search';import{DatasetsClient,BaseDataset}from'@brightdata/sdk/datasets';

Error Handling

The SDK exports typed error classes that extend BRDError:

import{bdclient,ValidationError,AuthenticationError,BRDError}from'@brightdata/sdk';try{constresult=awaitclient.scrapeUrl('https://example.com');}catch(error){if(errorinstanceofValidationError){console.error('Invalid input:',error.message);}elseif(errorinstanceofAuthenticationError){console.error('Auth failed:',error.message);}elseif(errorinstanceofBRDError){console.error('SDK error:',error.message);}}

Error types:ValidationError, AuthenticationError, ZoneError, NetworkError, NetworkTimeoutError, TimeoutError, APIError, DataNotReadyError, FSError

Troubleshooting

Windows & corporate networks

ProblemFix
npm.ps1 cannot be loaded because running scripts is disabled (PowerShell)Use cmd instead of PowerShell, or run npm.cmd <command>, or run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. If overridden by Group Policy, contact your IT team.
SELF_SIGNED_CERT_IN_CHAIN during npm installYour network uses SSL inspection. Point npm to your corporate root certificate: npm config set cafile "C:\path\to\corporate-root.cer"
Certificate errors at runtimeSet the env variable NODE_EXTRA_CA_CERTS=C:\path\to\corporate-root.cer so Node trusts your corporate certificate.

AuthenticationError: invalid API key

If you get this error, check the following in order:

  1. Verify the token itself works, outside the SDK:
    curl -H "Authorization: Bearer YOUR_TOKEN" https://api.brightdata.com/zone/get_active_zones
    If this fails, generate a new API key with admin permissions in the control panel. Note the SDK needs an account-level API token — not a zone password.
  2. Check for shell overrides. Environment variables set in your shell take precedence over .env files loaded with node --env-file=.env. Run set BRIGHTDATA (Windows) or env | grep BRIGHTDATA (macOS/Linux) and clear any leftover values.
  3. Check your .env file: no quotes, no spaces around =, no trailing whitespace, and the token copied exactly (including dashes). Prefer LF line endings.
  4. Print what actually loaded:
    console.log(JSON.stringify(process.env.BRIGHTDATA_API_TOKEN));
    Hidden characters like \r will be visible in the output.

Support

For any issues, contact Bright Data support, or open an issue in this repository.

License

This project is licensed under the MIT License.

About

Bright Data's JS SDK, use it to call bright data's scrape and search tools. bypass any Bot-detection or Captcha and extract data from the web.

Topics

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

sdk-banner(1)

Bright Data JavaScript SDK providing easy and scalable methods for scraping, web search, datasets, and more.

Installation @latest

npm install @brightdata/sdk

Quick start

1. Signup and get your API token

2. Initialize the client

import{bdclient}from'@brightdata/sdk';constclient=newbdclient({apiKey: '[your_api_token]',// or set BRIGHTDATA_API_TOKEN env variable});

3. Launch your first request

// Scrape a webpageconsthtml=awaitclient.scrapeUrl('https://example.com');console.log(html);// Search the webconstresults=awaitclient.search.google('pizza restaurants',{country: 'us'});console.log(results);

Don't forget to close when done:

awaitclient.close();

Features

  • Web Scraping — Scrape any website using anti-bot detection bypass and proxy support
  • Search Engine Results — Google, Bing, and Yandex search with batch support
  • Platform Scrapers — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
  • Crawl API — Crawl any URL(s) and get every output format (markdown, HTML, text) bundled per page
  • Discover API — AI-powered web search with intent-based relevance ranking
  • Scraper Studio — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
  • Browser API — CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers
  • Datasets — Access 126 pre-built datasets across dozens of platforms with query/download support
  • Parallel Processing — Concurrent processing for multiple URLs or queries
  • Robust Error Handling — Typed error classes with retry logic
  • Zone Management — Automatic zone creation and management
  • Multiple Output Formats — HTML, JSON, Markdown, and screenshots
  • Dual Build — Both ESM and CommonJS supported
  • TypeScript — Fully typed API with overloaded signatures
  • Subpath Exports — Tree-shakeable imports via @brightdata/sdk/scrapers, @brightdata/sdk/search, @brightdata/sdk/datasets

Usage

Scrape websites

// Single URL — returns HTML string by defaultconsthtml=awaitclient.scrapeUrl('https://example.com');// Multiple URLs (parallel processing)constresults=awaitclient.scrapeUrl(['https://example1.com','https://example2.com',]);// Get markdown contentconstmd=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'markdown',});// Get structured JSONconstdata=awaitclient.scrapeUrl('https://example.com',{format: 'json',});// Take a screenshotconstscreenshot=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'screenshot',});// Full optionsconstresult=awaitclient.scrapeUrl('https://example.com',{format: 'raw',// 'raw' (default) or 'json'dataFormat: 'html',// 'html' (default), 'markdown' (alias: 'md'), 'screenshot'country: 'gb',// two-letter country codemethod: 'GET',// HTTP method});

Search engines

// Google searchconstresults=awaitclient.search.google('pizza restaurants');// Bing searchconstresults=awaitclient.search.bing('pizza restaurants');// Yandex searchconstresults=awaitclient.search.yandex('pizza restaurants');// Batch search (parallel)constresults=awaitclient.search.google(['pizza','sushi','tacos']);// With optionsconstresults=awaitclient.search.google('pizza',{country: 'gb',format: 'json',});

Note: If country is not specified, requests exit through an arbitrary proxy location, so results may be geo-located to an unexpected country. Always pass country when you need consistent, localized results.

Platform scrapers

Collect structured data from popular platforms. Each platform supports sync collection (collect*) and async orchestrated scraping (trigger, poll, download).

// LinkedIn profilesconstdata=awaitclient.scrape.linkedin.collectProfiles(['https://www.linkedin.com/in/satyanadella/'],{format: 'json'},);// Amazon productsconstdata=awaitclient.scrape.amazon.collectProducts(['https://www.amazon.com/dp/B0D77BX8Y4'],{format: 'json'},);// Instagram profilesconstdata=awaitclient.scrape.instagram.collectProfiles(['https://www.instagram.com/natgeo/'],{format: 'json'},);// TikTok profilesconstdata=awaitclient.scrape.tiktok.collectProfiles(['https://www.tiktok.com/@tiktok'],{format: 'json'},);// YouTube videosconstdata=awaitclient.scrape.youtube.collectVideos(['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],{format: 'json'},);// Reddit postsconstdata=awaitclient.scrape.reddit.collectPosts(['https://www.reddit.com/r/technology/top/'],{format: 'json'},);

Orchestrated scraping (async trigger → poll → download):

constresult=awaitclient.scrape.linkedin.profiles(['https://www.linkedin.com/in/satyanadella/'],{pollInterval: 5000,pollTimeout: 180_000},);console.log(result.data);// structured dataconsole.log(result.status);// 'ready'console.log(result.rowCount);

Available platforms:linkedin, amazon, instagram, tiktok, youtube, reddit, facebook, pinterest, chatGPT, digikey, perplexity

Crawl API

Crawl one or more URLs and get every output format (markdown, HTML, text) bundled per page.

// Sync — single round-tripconstresult=awaitclient.crawler.crawl('https://example.com');console.log(result.data[0].markdown);// Batchconstresult=awaitclient.crawler.crawl(['https://example.com','https://example.com/about',]);console.log(`${result.pageCount} pages`);// Async — trigger, poll, downloadconstjob=awaitclient.crawler.trigger('https://example.com');conststatus=awaitclient.crawler.status(job.snapshotId);constresult=awaitclient.crawler.download(job.snapshotId);

Discover API

AI-powered web search with relevance ranking based on intent.

discover() resolves to a DiscoverResult wrapper (not a bare array). The items are on result.data (or its alias result.results), and the result is iterable. On failure result.success is false, result.error carries the reason, and result.data / result.results stay an empty array — so iterating never throws.

// Basic searchconstresult=awaitclient.discover('artificial intelligence trends 2026');if(!result.success){console.error('discover failed:',result.error);}else{console.log(result.results);// [{ link, title, description, relevance_score }, ...]for(constitemofresult){console.log(`[${item.relevance_score}] ${item.title}`);}}// With intent for semantic rankingconstresult=awaitclient.discover('Tesla battery technology',{intent: 'recent breakthroughs in EV battery chemistry',});// With filtering and localizationconstresult=awaitclient.discover('sustainable fashion brands',{intent: 'eco-friendly clothing companies',filterKeywords: ['sustainability','eco-friendly','organic'],country: 'us',numResults: 10,});// Include full page contentconstresult=awaitclient.discover('python asyncio tutorial',{includeContent: true,numResults: 3,});// Manual trigger/poll/fetchconstjob=awaitclient.discoverTrigger('market research SaaS',{intent: 'competitor pricing strategies',});awaitjob.wait({timeout: 60_000});constdata=awaitjob.fetch();

Scraper Studio

Trigger and fetch results from your custom scrapers built in Scraper Studio.

// Orchestrated — trigger + poll + return resultsconstresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: {url: 'https://example.com/product/1'},});// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }// Multiple inputs (processed sequentially)constresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: [{url: 'https://example.com/product/1'},{url: 'https://example.com/product/2'},],});// Manual control — trigger, then poll yourselfconstjob=awaitclient.scraperStudio.trigger('c_your_collector_id',{url: 'https://example.com/product/1',});constdata=awaitjob.waitAndFetch();// Check job status (by job ID from the dashboard)conststatus=awaitclient.scraperStudio.status('j_abc123');console.log(status.status);// 'queued' | 'running' | 'done' | 'failed'

Browser API

Build CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers. Credentials come from browserUsername/browserPassword options or BRIGHTDATA_BROWSERAPI_USERNAME/BRIGHTDATA_BROWSERAPI_PASSWORD env vars.

// Get a connection URLconsturl=client.browser.getConnectUrl();// Geo-target the browser with a 2-letter country codeconstusUrl=client.browser.getConnectUrl({country: 'us'});// Connect with Playwrightimport{chromium}from'playwright';constbrowser=awaitchromium.connectOverCDP(url);constpage=awaitbrowser.newPage();awaitpage.goto('https://example.com');consthtml=awaitpage.content();awaitbrowser.close();

Datasets

Access 126 pre-built datasets for querying and downloading structured data snapshots.

constds=client.datasets;// List all datasets available on your accountconstlist=awaitds.list();// Get field metadata for a datasetconstmeta=awaitds.instagramProfiles.getMetadata();console.log(meta.fields);// [{ name, type, description }, ...]// Query a dataset (triggers a snapshot)constsnapshotId=awaitds.instagramProfiles.query({url: 'https://www.instagram.com/natgeo/'},{records_limit: 10},);// Check snapshot statusconststatus=awaitds.instagramProfiles.getStatus(snapshotId);console.log(status.status);// 'running' | 'ready' | ...// Download when readyconstrows=awaitds.instagramProfiles.download(snapshotId);

Available datasets:

PlatformDatasets
LinkedInlinkedinProfiles, linkedinCompanies
AmazonamazonProducts, amazonReviews, amazonSellers, amazonBestSellers, amazonProductsSearch, amazonProductsGlobal, amazonWalmart
InstagraminstagramProfiles, instagramPosts, instagramComments, instagramReels
TikToktiktokProfiles, tiktokPosts, tiktokComments, tiktokShop
X/TwitterxTwitterPosts, xTwitterProfiles

Saving results

constdata=awaitclient.scrapeUrl('https://example.com');constfilePath=awaitclient.saveResults(data,{filename: 'results.json',format: 'json',});console.log(`Saved to: ${filePath}`);

Configuration

Runtime support

Node.js (>= 20) is the supported and tested runtime. The SDK also runs under Bun without crashing, but with a real caveat: Bun's bundled undici provides only a bare-bones Agent (no compose(), no close(), no custom dispatch), and Bun's request()/stream() ignore the dispatcher option entirely, routing through Bun's own native HTTP client instead. In practice this means requests still succeed under Bun, but none of Transport's tuning — connection pooling, keep-alive, custom timeouts, automatic retry on 429/500/502/503/504, and DNS caching — has any effect there; Bun's own defaults apply instead. The SDK detects the missing capabilities automatically (never crashes construction or close()), rather than failing.

API Token

Get your API token from Bright Data Control Panel.

Already logged in with the CLI? The SDK works with no configuration. If you've run brightdata login with the Bright Data CLI, the SDK automatically picks up those stored credentials. The token is resolved in this order:

  1. apiKey passed to new bdclient({ apiKey })
  2. BRIGHTDATA_API_TOKEN (or BRIGHTDATA_API_KEY) environment variable
  3. Credentials stored by the CLI (brightdata login)

If none are found, the client throws with instructions to log in or set a token.

Environment Variables

BRIGHTDATA_API_TOKEN=your_api_token# BRIGHTDATA_API_KEY also acceptedBRIGHTDATA_WEB_UNLOCKER_ZONE=your_web_unlocker_zone# OptionalBRIGHTDATA_SERP_ZONE=your_serp_zone# OptionalBRIGHTDATA_BROWSERAPI_USERNAME=your_browser_username# Optional, for Browser APIBRIGHTDATA_BROWSERAPI_PASSWORD=your_browser_password# Optional, for Browser APIBRIGHTDATA_VERBOSE=1# Optional, enable verbose logging

Tip: When loading these from a .env file with node --env-file=.env, note that variables already set in your shell take precedence over the file.

Client Options

constclient=newbdclient({apiKey: 'string',// API token (or use BRIGHTDATA_API_TOKEN env var)timeout: 120000,// Request timeout in ms (1000–300000)autoCreateZones: true,// Auto-create zones if they don't existwebUnlockerZone: 'string',// Custom web unlocker zone nameserpZone: 'string',// Custom SERP zone namelogLevel: 'INFO',// 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'structuredLogging: true,// Use structured JSON loggingverbose: false,// Enable verbose loggingrateLimit: 0,// Max requests per period (0 = unlimited)ratePeriod: 1000,// Rate limit period in ms});

Resource Cleanup

The client maintains HTTP connections. Always close when done:

awaitclient.close();// Or use Symbol.asyncDispose (TypeScript 5.2+)awaitusingclient=newbdclient();

Constants

ConstantDefaultDescription
DEFAULT_CONCURRENCY10Max parallel tasks
DEFAULT_TIMEOUT120000Request timeout (milliseconds)
MAX_RETRIES3Retry attempts on failure
RETRY_BACKOFF_FACTOR1.5Exponential backoff multiplier

Zone Management

constzones=awaitclient.listZones();console.log(`Found ${zones.length} zones`);

Subpath Exports

For tree-shaking or importing only what you need:

import{ScrapeRouter,LinkedinAPI}from'@brightdata/sdk/scrapers';import{SearchRouter}from'@brightdata/sdk/search';import{DatasetsClient,BaseDataset}from'@brightdata/sdk/datasets';

Error Handling

The SDK exports typed error classes that extend BRDError:

import{bdclient,ValidationError,AuthenticationError,BRDError}from'@brightdata/sdk';try{constresult=awaitclient.scrapeUrl('https://example.com');}catch(error){if(errorinstanceofValidationError){console.error('Invalid input:',error.message);}elseif(errorinstanceofAuthenticationError){console.error('Auth failed:',error.message);}elseif(errorinstanceofBRDError){console.error('SDK error:',error.message);}}

Error types:ValidationError, AuthenticationError, ZoneError, NetworkError, NetworkTimeoutError, TimeoutError, APIError, DataNotReadyError, FSError

Troubleshooting

Windows & corporate networks

ProblemFix
npm.ps1 cannot be loaded because running scripts is disabled (PowerShell)Use cmd instead of PowerShell, or run npm.cmd <command>, or run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. If overridden by Group Policy, contact your IT team.
SELF_SIGNED_CERT_IN_CHAIN during npm installYour network uses SSL inspection. Point npm to your corporate root certificate: npm config set cafile "C:\path\to\corporate-root.cer"
Certificate errors at runtimeSet the env variable NODE_EXTRA_CA_CERTS=C:\path\to\corporate-root.cer so Node trusts your corporate certificate.

AuthenticationError: invalid API key

If you get this error, check the following in order:

  1. Verify the token itself works, outside the SDK:
    curl -H "Authorization: Bearer YOUR_TOKEN" https://api.brightdata.com/zone/get_active_zones
    If this fails, generate a new API key with admin permissions in the control panel. Note the SDK needs an account-level API token — not a zone password.
  2. Check for shell overrides. Environment variables set in your shell take precedence over .env files loaded with node --env-file=.env. Run set BRIGHTDATA (Windows) or env | grep BRIGHTDATA (macOS/Linux) and clear any leftover values.
  3. Check your .env file: no quotes, no spaces around =, no trailing whitespace, and the token copied exactly (including dashes). Prefer LF line endings.
  4. Print what actually loaded:
    console.log(JSON.stringify(process.env.BRIGHTDATA_API_TOKEN));
    Hidden characters like \r will be visible in the output.

Support

For any issues, contact Bright Data support, or open an issue in this repository.

License

This project is licensed under the MIT License.

About

Bright Data's JS SDK, use it to call bright data's scrape and search tools. bypass any Bot-detection or Captcha and extract data from the web.

Topics

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

sdk-banner(1)

Bright Data JavaScript SDK providing easy and scalable methods for scraping, web search, datasets, and more.

Installation @latest

npm install @brightdata/sdk

Quick start

1. Signup and get your API token

2. Initialize the client

import{bdclient}from'@brightdata/sdk';constclient=newbdclient({apiKey: '[your_api_token]',// or set BRIGHTDATA_API_TOKEN env variable});

3. Launch your first request

// Scrape a webpageconsthtml=awaitclient.scrapeUrl('https://example.com');console.log(html);// Search the webconstresults=awaitclient.search.google('pizza restaurants',{country: 'us'});console.log(results);

Don't forget to close when done:

awaitclient.close();

Features

  • Web Scraping — Scrape any website using anti-bot detection bypass and proxy support
  • Search Engine Results — Google, Bing, and Yandex search with batch support
  • Platform Scrapers — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
  • Crawl API — Crawl any URL(s) and get every output format (markdown, HTML, text) bundled per page
  • Discover API — AI-powered web search with intent-based relevance ranking
  • Scraper Studio — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
  • Browser API — CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers
  • Datasets — Access 126 pre-built datasets across dozens of platforms with query/download support
  • Parallel Processing — Concurrent processing for multiple URLs or queries
  • Robust Error Handling — Typed error classes with retry logic
  • Zone Management — Automatic zone creation and management
  • Multiple Output Formats — HTML, JSON, Markdown, and screenshots
  • Dual Build — Both ESM and CommonJS supported
  • TypeScript — Fully typed API with overloaded signatures
  • Subpath Exports — Tree-shakeable imports via @brightdata/sdk/scrapers, @brightdata/sdk/search, @brightdata/sdk/datasets

Usage

Scrape websites

// Single URL — returns HTML string by defaultconsthtml=awaitclient.scrapeUrl('https://example.com');// Multiple URLs (parallel processing)constresults=awaitclient.scrapeUrl(['https://example1.com','https://example2.com',]);// Get markdown contentconstmd=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'markdown',});// Get structured JSONconstdata=awaitclient.scrapeUrl('https://example.com',{format: 'json',});// Take a screenshotconstscreenshot=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'screenshot',});// Full optionsconstresult=awaitclient.scrapeUrl('https://example.com',{format: 'raw',// 'raw' (default) or 'json'dataFormat: 'html',// 'html' (default), 'markdown' (alias: 'md'), 'screenshot'country: 'gb',// two-letter country codemethod: 'GET',// HTTP method});

Search engines

// Google searchconstresults=awaitclient.search.google('pizza restaurants');// Bing searchconstresults=awaitclient.search.bing('pizza restaurants');// Yandex searchconstresults=awaitclient.search.yandex('pizza restaurants');// Batch search (parallel)constresults=awaitclient.search.google(['pizza','sushi','tacos']);// With optionsconstresults=awaitclient.search.google('pizza',{country: 'gb',format: 'json',});

Note: If country is not specified, requests exit through an arbitrary proxy location, so results may be geo-located to an unexpected country. Always pass country when you need consistent, localized results.

Platform scrapers

Collect structured data from popular platforms. Each platform supports sync collection (collect*) and async orchestrated scraping (trigger, poll, download).

// LinkedIn profilesconstdata=awaitclient.scrape.linkedin.collectProfiles(['https://www.linkedin.com/in/satyanadella/'],{format: 'json'},);// Amazon productsconstdata=awaitclient.scrape.amazon.collectProducts(['https://www.amazon.com/dp/B0D77BX8Y4'],{format: 'json'},);// Instagram profilesconstdata=awaitclient.scrape.instagram.collectProfiles(['https://www.instagram.com/natgeo/'],{format: 'json'},);// TikTok profilesconstdata=awaitclient.scrape.tiktok.collectProfiles(['https://www.tiktok.com/@tiktok'],{format: 'json'},);// YouTube videosconstdata=awaitclient.scrape.youtube.collectVideos(['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],{format: 'json'},);// Reddit postsconstdata=awaitclient.scrape.reddit.collectPosts(['https://www.reddit.com/r/technology/top/'],{format: 'json'},);

Orchestrated scraping (async trigger → poll → download):

constresult=awaitclient.scrape.linkedin.profiles(['https://www.linkedin.com/in/satyanadella/'],{pollInterval: 5000,pollTimeout: 180_000},);console.log(result.data);// structured dataconsole.log(result.status);// 'ready'console.log(result.rowCount);

Available platforms:linkedin, amazon, instagram, tiktok, youtube, reddit, facebook, pinterest, chatGPT, digikey, perplexity

Crawl API

Crawl one or more URLs and get every output format (markdown, HTML, text) bundled per page.

// Sync — single round-tripconstresult=awaitclient.crawler.crawl('https://example.com');console.log(result.data[0].markdown);// Batchconstresult=awaitclient.crawler.crawl(['https://example.com','https://example.com/about',]);console.log(`${result.pageCount} pages`);// Async — trigger, poll, downloadconstjob=awaitclient.crawler.trigger('https://example.com');conststatus=awaitclient.crawler.status(job.snapshotId);constresult=awaitclient.crawler.download(job.snapshotId);

Discover API

AI-powered web search with relevance ranking based on intent.

discover() resolves to a DiscoverResult wrapper (not a bare array). The items are on result.data (or its alias result.results), and the result is iterable. On failure result.success is false, result.error carries the reason, and result.data / result.results stay an empty array — so iterating never throws.

// Basic searchconstresult=awaitclient.discover('artificial intelligence trends 2026');if(!result.success){console.error('discover failed:',result.error);}else{console.log(result.results);// [{ link, title, description, relevance_score }, ...]for(constitemofresult){console.log(`[${item.relevance_score}] ${item.title}`);}}// With intent for semantic rankingconstresult=awaitclient.discover('Tesla battery technology',{intent: 'recent breakthroughs in EV battery chemistry',});// With filtering and localizationconstresult=awaitclient.discover('sustainable fashion brands',{intent: 'eco-friendly clothing companies',filterKeywords: ['sustainability','eco-friendly','organic'],country: 'us',numResults: 10,});// Include full page contentconstresult=awaitclient.discover('python asyncio tutorial',{includeContent: true,numResults: 3,});// Manual trigger/poll/fetchconstjob=awaitclient.discoverTrigger('market research SaaS',{intent: 'competitor pricing strategies',});awaitjob.wait({timeout: 60_000});constdata=awaitjob.fetch();

Scraper Studio

Trigger and fetch results from your custom scrapers built in Scraper Studio.

// Orchestrated — trigger + poll + return resultsconstresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: {url: 'https://example.com/product/1'},});// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }// Multiple inputs (processed sequentially)constresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: [{url: 'https://example.com/product/1'},{url: 'https://example.com/product/2'},],});// Manual control — trigger, then poll yourselfconstjob=awaitclient.scraperStudio.trigger('c_your_collector_id',{url: 'https://example.com/product/1',});constdata=awaitjob.waitAndFetch();// Check job status (by job ID from the dashboard)conststatus=awaitclient.scraperStudio.status('j_abc123');console.log(status.status);// 'queued' | 'running' | 'done' | 'failed'

Browser API

Build CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers. Credentials come from browserUsername/browserPassword options or BRIGHTDATA_BROWSERAPI_USERNAME/BRIGHTDATA_BROWSERAPI_PASSWORD env vars.

// Get a connection URLconsturl=client.browser.getConnectUrl();// Geo-target the browser with a 2-letter country codeconstusUrl=client.browser.getConnectUrl({country: 'us'});// Connect with Playwrightimport{chromium}from'playwright';constbrowser=awaitchromium.connectOverCDP(url);constpage=awaitbrowser.newPage();awaitpage.goto('https://example.com');consthtml=awaitpage.content();awaitbrowser.close();

Datasets

Access 126 pre-built datasets for querying and downloading structured data snapshots.

constds=client.datasets;// List all datasets available on your accountconstlist=awaitds.list();// Get field metadata for a datasetconstmeta=awaitds.instagramProfiles.getMetadata();console.log(meta.fields);// [{ name, type, description }, ...]// Query a dataset (triggers a snapshot)constsnapshotId=awaitds.instagramProfiles.query({url: 'https://www.instagram.com/natgeo/'},{records_limit: 10},);// Check snapshot statusconststatus=awaitds.instagramProfiles.getStatus(snapshotId);console.log(status.status);// 'running' | 'ready' | ...// Download when readyconstrows=awaitds.instagramProfiles.download(snapshotId);

Available datasets:

PlatformDatasets
LinkedInlinkedinProfiles, linkedinCompanies
AmazonamazonProducts, amazonReviews, amazonSellers, amazonBestSellers, amazonProductsSearch, amazonProductsGlobal, amazonWalmart
InstagraminstagramProfiles, instagramPosts, instagramComments, instagramReels
TikToktiktokProfiles, tiktokPosts, tiktokComments, tiktokShop
X/TwitterxTwitterPosts, xTwitterProfiles

Saving results

constdata=awaitclient.scrapeUrl('https://example.com');constfilePath=awaitclient.saveResults(data,{filename: 'results.json',format: 'json',});console.log(`Saved to: ${filePath}`);

Configuration

Runtime support

Node.js (>= 20) is the supported and tested runtime. The SDK also runs under Bun without crashing, but with a real caveat: Bun's bundled undici provides only a bare-bones Agent (no compose(), no close(), no custom dispatch), and Bun's request()/stream() ignore the dispatcher option entirely, routing through Bun's own native HTTP client instead. In practice this means requests still succeed under Bun, but none of Transport's tuning — connection pooling, keep-alive, custom timeouts, automatic retry on 429/500/502/503/504, and DNS caching — has any effect there; Bun's own defaults apply instead. The SDK detects the missing capabilities automatically (never crashes construction or close()), rather than failing.

API Token

Get your API token from Bright Data Control Panel.

Already logged in with the CLI? The SDK works with no configuration. If you've run brightdata login with the Bright Data CLI, the SDK automatically picks up those stored credentials. The token is resolved in this order:

  1. apiKey passed to new bdclient({ apiKey })
  2. BRIGHTDATA_API_TOKEN (or BRIGHTDATA_API_KEY) environment variable
  3. Credentials stored by the CLI (brightdata login)

If none are found, the client throws with instructions to log in or set a token.

Environment Variables

BRIGHTDATA_API_TOKEN=your_api_token# BRIGHTDATA_API_KEY also acceptedBRIGHTDATA_WEB_UNLOCKER_ZONE=your_web_unlocker_zone# OptionalBRIGHTDATA_SERP_ZONE=your_serp_zone# OptionalBRIGHTDATA_BROWSERAPI_USERNAME=your_browser_username# Optional, for Browser APIBRIGHTDATA_BROWSERAPI_PASSWORD=your_browser_password# Optional, for Browser APIBRIGHTDATA_VERBOSE=1# Optional, enable verbose logging

Tip: When loading these from a .env file with node --env-file=.env, note that variables already set in your shell take precedence over the file.

Client Options

constclient=newbdclient({apiKey: 'string',// API token (or use BRIGHTDATA_API_TOKEN env var)timeout: 120000,// Request timeout in ms (1000–300000)autoCreateZones: true,// Auto-create zones if they don't existwebUnlockerZone: 'string',// Custom web unlocker zone nameserpZone: 'string',// Custom SERP zone namelogLevel: 'INFO',// 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'structuredLogging: true,// Use structured JSON loggingverbose: false,// Enable verbose loggingrateLimit: 0,// Max requests per period (0 = unlimited)ratePeriod: 1000,// Rate limit period in ms});

Resource Cleanup

The client maintains HTTP connections. Always close when done:

awaitclient.close();// Or use Symbol.asyncDispose (TypeScript 5.2+)awaitusingclient=newbdclient();

Constants

ConstantDefaultDescription
DEFAULT_CONCURRENCY10Max parallel tasks
DEFAULT_TIMEOUT120000Request timeout (milliseconds)
MAX_RETRIES3Retry attempts on failure
RETRY_BACKOFF_FACTOR1.5Exponential backoff multiplier

Zone Management

constzones=awaitclient.listZones();console.log(`Found ${zones.length} zones`);

Subpath Exports

For tree-shaking or importing only what you need:

import{ScrapeRouter,LinkedinAPI}from'@brightdata/sdk/scrapers';import{SearchRouter}from'@brightdata/sdk/search';import{DatasetsClient,BaseDataset}from'@brightdata/sdk/datasets';

Error Handling

The SDK exports typed error classes that extend BRDError:

import{bdclient,ValidationError,AuthenticationError,BRDError}from'@brightdata/sdk';try{constresult=awaitclient.scrapeUrl('https://example.com');}catch(error){if(errorinstanceofValidationError){console.error('Invalid input:',error.message);}elseif(errorinstanceofAuthenticationError){console.error('Auth failed:',error.message);}elseif(errorinstanceofBRDError){console.error('SDK error:',error.message);}}

Error types:ValidationError, AuthenticationError, ZoneError, NetworkError, NetworkTimeoutError, TimeoutError, APIError, DataNotReadyError, FSError

Troubleshooting

Windows & corporate networks

ProblemFix
npm.ps1 cannot be loaded because running scripts is disabled (PowerShell)Use cmd instead of PowerShell, or run npm.cmd <command>, or run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. If overridden by Group Policy, contact your IT team.
SELF_SIGNED_CERT_IN_CHAIN during npm installYour network uses SSL inspection. Point npm to your corporate root certificate: npm config set cafile "C:\path\to\corporate-root.cer"
Certificate errors at runtimeSet the env variable NODE_EXTRA_CA_CERTS=C:\path\to\corporate-root.cer so Node trusts your corporate certificate.

AuthenticationError: invalid API key

If you get this error, check the following in order:

  1. Verify the token itself works, outside the SDK:
    curl -H "Authorization: Bearer YOUR_TOKEN" https://api.brightdata.com/zone/get_active_zones
    If this fails, generate a new API key with admin permissions in the control panel. Note the SDK needs an account-level API token — not a zone password.
  2. Check for shell overrides. Environment variables set in your shell take precedence over .env files loaded with node --env-file=.env. Run set BRIGHTDATA (Windows) or env | grep BRIGHTDATA (macOS/Linux) and clear any leftover values.
  3. Check your .env file: no quotes, no spaces around =, no trailing whitespace, and the token copied exactly (including dashes). Prefer LF line endings.
  4. Print what actually loaded:
    console.log(JSON.stringify(process.env.BRIGHTDATA_API_TOKEN));
    Hidden characters like \r will be visible in the output.

Support

For any issues, contact Bright Data support, or open an issue in this repository.

License

This project is licensed under the MIT License.

About

Bright Data's JS SDK, use it to call bright data's scrape and search tools. bypass any Bot-detection or Captcha and extract data from the web.

Topics

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

sdk-banner(1)

Bright Data JavaScript SDK providing easy and scalable methods for scraping, web search, datasets, and more.

Installation @latest

npm install @brightdata/sdk

Quick start

1. Signup and get your API token

2. Initialize the client

import{bdclient}from'@brightdata/sdk';constclient=newbdclient({apiKey: '[your_api_token]',// or set BRIGHTDATA_API_TOKEN env variable});

3. Launch your first request

// Scrape a webpageconsthtml=awaitclient.scrapeUrl('https://example.com');console.log(html);// Search the webconstresults=awaitclient.search.google('pizza restaurants',{country: 'us'});console.log(results);

Don't forget to close when done:

awaitclient.close();

Features

  • Web Scraping — Scrape any website using anti-bot detection bypass and proxy support
  • Search Engine Results — Google, Bing, and Yandex search with batch support
  • Platform Scrapers — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
  • Crawl API — Crawl any URL(s) and get every output format (markdown, HTML, text) bundled per page
  • Discover API — AI-powered web search with intent-based relevance ranking
  • Scraper Studio — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
  • Browser API — CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers
  • Datasets — Access 126 pre-built datasets across dozens of platforms with query/download support
  • Parallel Processing — Concurrent processing for multiple URLs or queries
  • Robust Error Handling — Typed error classes with retry logic
  • Zone Management — Automatic zone creation and management
  • Multiple Output Formats — HTML, JSON, Markdown, and screenshots
  • Dual Build — Both ESM and CommonJS supported
  • TypeScript — Fully typed API with overloaded signatures
  • Subpath Exports — Tree-shakeable imports via @brightdata/sdk/scrapers, @brightdata/sdk/search, @brightdata/sdk/datasets

Usage

Scrape websites

// Single URL — returns HTML string by defaultconsthtml=awaitclient.scrapeUrl('https://example.com');// Multiple URLs (parallel processing)constresults=awaitclient.scrapeUrl(['https://example1.com','https://example2.com',]);// Get markdown contentconstmd=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'markdown',});// Get structured JSONconstdata=awaitclient.scrapeUrl('https://example.com',{format: 'json',});// Take a screenshotconstscreenshot=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'screenshot',});// Full optionsconstresult=awaitclient.scrapeUrl('https://example.com',{format: 'raw',// 'raw' (default) or 'json'dataFormat: 'html',// 'html' (default), 'markdown' (alias: 'md'), 'screenshot'country: 'gb',// two-letter country codemethod: 'GET',// HTTP method});

Search engines

// Google searchconstresults=awaitclient.search.google('pizza restaurants');// Bing searchconstresults=awaitclient.search.bing('pizza restaurants');// Yandex searchconstresults=awaitclient.search.yandex('pizza restaurants');// Batch search (parallel)constresults=awaitclient.search.google(['pizza','sushi','tacos']);// With optionsconstresults=awaitclient.search.google('pizza',{country: 'gb',format: 'json',});

Note: If country is not specified, requests exit through an arbitrary proxy location, so results may be geo-located to an unexpected country. Always pass country when you need consistent, localized results.

Platform scrapers

Collect structured data from popular platforms. Each platform supports sync collection (collect*) and async orchestrated scraping (trigger, poll, download).

// LinkedIn profilesconstdata=awaitclient.scrape.linkedin.collectProfiles(['https://www.linkedin.com/in/satyanadella/'],{format: 'json'},);// Amazon productsconstdata=awaitclient.scrape.amazon.collectProducts(['https://www.amazon.com/dp/B0D77BX8Y4'],{format: 'json'},);// Instagram profilesconstdata=awaitclient.scrape.instagram.collectProfiles(['https://www.instagram.com/natgeo/'],{format: 'json'},);// TikTok profilesconstdata=awaitclient.scrape.tiktok.collectProfiles(['https://www.tiktok.com/@tiktok'],{format: 'json'},);// YouTube videosconstdata=awaitclient.scrape.youtube.collectVideos(['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],{format: 'json'},);// Reddit postsconstdata=awaitclient.scrape.reddit.collectPosts(['https://www.reddit.com/r/technology/top/'],{format: 'json'},);

Orchestrated scraping (async trigger → poll → download):

constresult=awaitclient.scrape.linkedin.profiles(['https://www.linkedin.com/in/satyanadella/'],{pollInterval: 5000,pollTimeout: 180_000},);console.log(result.data);// structured dataconsole.log(result.status);// 'ready'console.log(result.rowCount);

Available platforms:linkedin, amazon, instagram, tiktok, youtube, reddit, facebook, pinterest, chatGPT, digikey, perplexity

Crawl API

Crawl one or more URLs and get every output format (markdown, HTML, text) bundled per page.

// Sync — single round-tripconstresult=awaitclient.crawler.crawl('https://example.com');console.log(result.data[0].markdown);// Batchconstresult=awaitclient.crawler.crawl(['https://example.com','https://example.com/about',]);console.log(`${result.pageCount} pages`);// Async — trigger, poll, downloadconstjob=awaitclient.crawler.trigger('https://example.com');conststatus=awaitclient.crawler.status(job.snapshotId);constresult=awaitclient.crawler.download(job.snapshotId);

Discover API

AI-powered web search with relevance ranking based on intent.

discover() resolves to a DiscoverResult wrapper (not a bare array). The items are on result.data (or its alias result.results), and the result is iterable. On failure result.success is false, result.error carries the reason, and result.data / result.results stay an empty array — so iterating never throws.

// Basic searchconstresult=awaitclient.discover('artificial intelligence trends 2026');if(!result.success){console.error('discover failed:',result.error);}else{console.log(result.results);// [{ link, title, description, relevance_score }, ...]for(constitemofresult){console.log(`[${item.relevance_score}] ${item.title}`);}}// With intent for semantic rankingconstresult=awaitclient.discover('Tesla battery technology',{intent: 'recent breakthroughs in EV battery chemistry',});// With filtering and localizationconstresult=awaitclient.discover('sustainable fashion brands',{intent: 'eco-friendly clothing companies',filterKeywords: ['sustainability','eco-friendly','organic'],country: 'us',numResults: 10,});// Include full page contentconstresult=awaitclient.discover('python asyncio tutorial',{includeContent: true,numResults: 3,});// Manual trigger/poll/fetchconstjob=awaitclient.discoverTrigger('market research SaaS',{intent: 'competitor pricing strategies',});awaitjob.wait({timeout: 60_000});constdata=awaitjob.fetch();

Scraper Studio

Trigger and fetch results from your custom scrapers built in Scraper Studio.

// Orchestrated — trigger + poll + return resultsconstresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: {url: 'https://example.com/product/1'},});// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }// Multiple inputs (processed sequentially)constresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: [{url: 'https://example.com/product/1'},{url: 'https://example.com/product/2'},],});// Manual control — trigger, then poll yourselfconstjob=awaitclient.scraperStudio.trigger('c_your_collector_id',{url: 'https://example.com/product/1',});constdata=awaitjob.waitAndFetch();// Check job status (by job ID from the dashboard)conststatus=awaitclient.scraperStudio.status('j_abc123');console.log(status.status);// 'queued' | 'running' | 'done' | 'failed'

Browser API

Build CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers. Credentials come from browserUsername/browserPassword options or BRIGHTDATA_BROWSERAPI_USERNAME/BRIGHTDATA_BROWSERAPI_PASSWORD env vars.

// Get a connection URLconsturl=client.browser.getConnectUrl();// Geo-target the browser with a 2-letter country codeconstusUrl=client.browser.getConnectUrl({country: 'us'});// Connect with Playwrightimport{chromium}from'playwright';constbrowser=awaitchromium.connectOverCDP(url);constpage=awaitbrowser.newPage();awaitpage.goto('https://example.com');consthtml=awaitpage.content();awaitbrowser.close();

Datasets

Access 126 pre-built datasets for querying and downloading structured data snapshots.

constds=client.datasets;// List all datasets available on your accountconstlist=awaitds.list();// Get field metadata for a datasetconstmeta=awaitds.instagramProfiles.getMetadata();console.log(meta.fields);// [{ name, type, description }, ...]// Query a dataset (triggers a snapshot)constsnapshotId=awaitds.instagramProfiles.query({url: 'https://www.instagram.com/natgeo/'},{records_limit: 10},);// Check snapshot statusconststatus=awaitds.instagramProfiles.getStatus(snapshotId);console.log(status.status);// 'running' | 'ready' | ...// Download when readyconstrows=awaitds.instagramProfiles.download(snapshotId);

Available datasets:

PlatformDatasets
LinkedInlinkedinProfiles, linkedinCompanies
AmazonamazonProducts, amazonReviews, amazonSellers, amazonBestSellers, amazonProductsSearch, amazonProductsGlobal, amazonWalmart
InstagraminstagramProfiles, instagramPosts, instagramComments, instagramReels
TikToktiktokProfiles, tiktokPosts, tiktokComments, tiktokShop
X/TwitterxTwitterPosts, xTwitterProfiles

Saving results

constdata=awaitclient.scrapeUrl('https://example.com');constfilePath=awaitclient.saveResults(data,{filename: 'results.json',format: 'json',});console.log(`Saved to: ${filePath}`);

Configuration

Runtime support

Node.js (>= 20) is the supported and tested runtime. The SDK also runs under Bun without crashing, but with a real caveat: Bun's bundled undici provides only a bare-bones Agent (no compose(), no close(), no custom dispatch), and Bun's request()/stream() ignore the dispatcher option entirely, routing through Bun's own native HTTP client instead. In practice this means requests still succeed under Bun, but none of Transport's tuning — connection pooling, keep-alive, custom timeouts, automatic retry on 429/500/502/503/504, and DNS caching — has any effect there; Bun's own defaults apply instead. The SDK detects the missing capabilities automatically (never crashes construction or close()), rather than failing.

API Token

Get your API token from Bright Data Control Panel.

Already logged in with the CLI? The SDK works with no configuration. If you've run brightdata login with the Bright Data CLI, the SDK automatically picks up those stored credentials. The token is resolved in this order:

  1. apiKey passed to new bdclient({ apiKey })
  2. BRIGHTDATA_API_TOKEN (or BRIGHTDATA_API_KEY) environment variable
  3. Credentials stored by the CLI (brightdata login)

If none are found, the client throws with instructions to log in or set a token.

Environment Variables

BRIGHTDATA_API_TOKEN=your_api_token# BRIGHTDATA_API_KEY also acceptedBRIGHTDATA_WEB_UNLOCKER_ZONE=your_web_unlocker_zone# OptionalBRIGHTDATA_SERP_ZONE=your_serp_zone# OptionalBRIGHTDATA_BROWSERAPI_USERNAME=your_browser_username# Optional, for Browser APIBRIGHTDATA_BROWSERAPI_PASSWORD=your_browser_password# Optional, for Browser APIBRIGHTDATA_VERBOSE=1# Optional, enable verbose logging

Tip: When loading these from a .env file with node --env-file=.env, note that variables already set in your shell take precedence over the file.

Client Options

constclient=newbdclient({apiKey: 'string',// API token (or use BRIGHTDATA_API_TOKEN env var)timeout: 120000,// Request timeout in ms (1000–300000)autoCreateZones: true,// Auto-create zones if they don't existwebUnlockerZone: 'string',// Custom web unlocker zone nameserpZone: 'string',// Custom SERP zone namelogLevel: 'INFO',// 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'structuredLogging: true,// Use structured JSON loggingverbose: false,// Enable verbose loggingrateLimit: 0,// Max requests per period (0 = unlimited)ratePeriod: 1000,// Rate limit period in ms});

Resource Cleanup

The client maintains HTTP connections. Always close when done:

awaitclient.close();// Or use Symbol.asyncDispose (TypeScript 5.2+)awaitusingclient=newbdclient();

Constants

ConstantDefaultDescription
DEFAULT_CONCURRENCY10Max parallel tasks
DEFAULT_TIMEOUT120000Request timeout (milliseconds)
MAX_RETRIES3Retry attempts on failure
RETRY_BACKOFF_FACTOR1.5Exponential backoff multiplier

Zone Management

constzones=awaitclient.listZones();console.log(`Found ${zones.length} zones`);

Subpath Exports

For tree-shaking or importing only what you need:

import{ScrapeRouter,LinkedinAPI}from'@brightdata/sdk/scrapers';import{SearchRouter}from'@brightdata/sdk/search';import{DatasetsClient,BaseDataset}from'@brightdata/sdk/datasets';

Error Handling

The SDK exports typed error classes that extend BRDError:

import{bdclient,ValidationError,AuthenticationError,BRDError}from'@brightdata/sdk';try{constresult=awaitclient.scrapeUrl('https://example.com');}catch(error){if(errorinstanceofValidationError){console.error('Invalid input:',error.message);}elseif(errorinstanceofAuthenticationError){console.error('Auth failed:',error.message);}elseif(errorinstanceofBRDError){console.error('SDK error:',error.message);}}

Error types:ValidationError, AuthenticationError, ZoneError, NetworkError, NetworkTimeoutError, TimeoutError, APIError, DataNotReadyError, FSError

Troubleshooting

Windows & corporate networks

ProblemFix
npm.ps1 cannot be loaded because running scripts is disabled (PowerShell)Use cmd instead of PowerShell, or run npm.cmd <command>, or run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. If overridden by Group Policy, contact your IT team.
SELF_SIGNED_CERT_IN_CHAIN during npm installYour network uses SSL inspection. Point npm to your corporate root certificate: npm config set cafile "C:\path\to\corporate-root.cer"
Certificate errors at runtimeSet the env variable NODE_EXTRA_CA_CERTS=C:\path\to\corporate-root.cer so Node trusts your corporate certificate.

AuthenticationError: invalid API key

If you get this error, check the following in order:

  1. Verify the token itself works, outside the SDK:
    curl -H "Authorization: Bearer YOUR_TOKEN" https://api.brightdata.com/zone/get_active_zones
    If this fails, generate a new API key with admin permissions in the control panel. Note the SDK needs an account-level API token — not a zone password.
  2. Check for shell overrides. Environment variables set in your shell take precedence over .env files loaded with node --env-file=.env. Run set BRIGHTDATA (Windows) or env | grep BRIGHTDATA (macOS/Linux) and clear any leftover values.
  3. Check your .env file: no quotes, no spaces around =, no trailing whitespace, and the token copied exactly (including dashes). Prefer LF line endings.
  4. Print what actually loaded:
    console.log(JSON.stringify(process.env.BRIGHTDATA_API_TOKEN));
    Hidden characters like \r will be visible in the output.

Support

For any issues, contact Bright Data support, or open an issue in this repository.

License

This project is licensed under the MIT License.

About

Bright Data's JS SDK, use it to call bright data's scrape and search tools. bypass any Bot-detection or Captcha and extract data from the web.

Topics

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

sdk-banner(1)

Bright Data JavaScript SDK providing easy and scalable methods for scraping, web search, datasets, and more.

Installation @latest

npm install @brightdata/sdk

Quick start

1. Signup and get your API token

2. Initialize the client

import{bdclient}from'@brightdata/sdk';constclient=newbdclient({apiKey: '[your_api_token]',// or set BRIGHTDATA_API_TOKEN env variable});

3. Launch your first request

// Scrape a webpageconsthtml=awaitclient.scrapeUrl('https://example.com');console.log(html);// Search the webconstresults=awaitclient.search.google('pizza restaurants',{country: 'us'});console.log(results);

Don't forget to close when done:

awaitclient.close();

Features

  • Web Scraping — Scrape any website using anti-bot detection bypass and proxy support
  • Search Engine Results — Google, Bing, and Yandex search with batch support
  • Platform Scrapers — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
  • Crawl API — Crawl any URL(s) and get every output format (markdown, HTML, text) bundled per page
  • Discover API — AI-powered web search with intent-based relevance ranking
  • Scraper Studio — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
  • Browser API — CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers
  • Datasets — Access 126 pre-built datasets across dozens of platforms with query/download support
  • Parallel Processing — Concurrent processing for multiple URLs or queries
  • Robust Error Handling — Typed error classes with retry logic
  • Zone Management — Automatic zone creation and management
  • Multiple Output Formats — HTML, JSON, Markdown, and screenshots
  • Dual Build — Both ESM and CommonJS supported
  • TypeScript — Fully typed API with overloaded signatures
  • Subpath Exports — Tree-shakeable imports via @brightdata/sdk/scrapers, @brightdata/sdk/search, @brightdata/sdk/datasets

Usage

Scrape websites

// Single URL — returns HTML string by defaultconsthtml=awaitclient.scrapeUrl('https://example.com');// Multiple URLs (parallel processing)constresults=awaitclient.scrapeUrl(['https://example1.com','https://example2.com',]);// Get markdown contentconstmd=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'markdown',});// Get structured JSONconstdata=awaitclient.scrapeUrl('https://example.com',{format: 'json',});// Take a screenshotconstscreenshot=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'screenshot',});// Full optionsconstresult=awaitclient.scrapeUrl('https://example.com',{format: 'raw',// 'raw' (default) or 'json'dataFormat: 'html',// 'html' (default), 'markdown' (alias: 'md'), 'screenshot'country: 'gb',// two-letter country codemethod: 'GET',// HTTP method});

Search engines

// Google searchconstresults=awaitclient.search.google('pizza restaurants');// Bing searchconstresults=awaitclient.search.bing('pizza restaurants');// Yandex searchconstresults=awaitclient.search.yandex('pizza restaurants');// Batch search (parallel)constresults=awaitclient.search.google(['pizza','sushi','tacos']);// With optionsconstresults=awaitclient.search.google('pizza',{country: 'gb',format: 'json',});

Note: If country is not specified, requests exit through an arbitrary proxy location, so results may be geo-located to an unexpected country. Always pass country when you need consistent, localized results.

Platform scrapers

Collect structured data from popular platforms. Each platform supports sync collection (collect*) and async orchestrated scraping (trigger, poll, download).

// LinkedIn profilesconstdata=awaitclient.scrape.linkedin.collectProfiles(['https://www.linkedin.com/in/satyanadella/'],{format: 'json'},);// Amazon productsconstdata=awaitclient.scrape.amazon.collectProducts(['https://www.amazon.com/dp/B0D77BX8Y4'],{format: 'json'},);// Instagram profilesconstdata=awaitclient.scrape.instagram.collectProfiles(['https://www.instagram.com/natgeo/'],{format: 'json'},);// TikTok profilesconstdata=awaitclient.scrape.tiktok.collectProfiles(['https://www.tiktok.com/@tiktok'],{format: 'json'},);// YouTube videosconstdata=awaitclient.scrape.youtube.collectVideos(['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],{format: 'json'},);// Reddit postsconstdata=awaitclient.scrape.reddit.collectPosts(['https://www.reddit.com/r/technology/top/'],{format: 'json'},);

Orchestrated scraping (async trigger → poll → download):

constresult=awaitclient.scrape.linkedin.profiles(['https://www.linkedin.com/in/satyanadella/'],{pollInterval: 5000,pollTimeout: 180_000},);console.log(result.data);// structured dataconsole.log(result.status);// 'ready'console.log(result.rowCount);

Available platforms:linkedin, amazon, instagram, tiktok, youtube, reddit, facebook, pinterest, chatGPT, digikey, perplexity

Crawl API

Crawl one or more URLs and get every output format (markdown, HTML, text) bundled per page.

// Sync — single round-tripconstresult=awaitclient.crawler.crawl('https://example.com');console.log(result.data[0].markdown);// Batchconstresult=awaitclient.crawler.crawl(['https://example.com','https://example.com/about',]);console.log(`${result.pageCount} pages`);// Async — trigger, poll, downloadconstjob=awaitclient.crawler.trigger('https://example.com');conststatus=awaitclient.crawler.status(job.snapshotId);constresult=awaitclient.crawler.download(job.snapshotId);

Discover API

AI-powered web search with relevance ranking based on intent.

discover() resolves to a DiscoverResult wrapper (not a bare array). The items are on result.data (or its alias result.results), and the result is iterable. On failure result.success is false, result.error carries the reason, and result.data / result.results stay an empty array — so iterating never throws.

// Basic searchconstresult=awaitclient.discover('artificial intelligence trends 2026');if(!result.success){console.error('discover failed:',result.error);}else{console.log(result.results);// [{ link, title, description, relevance_score }, ...]for(constitemofresult){console.log(`[${item.relevance_score}] ${item.title}`);}}// With intent for semantic rankingconstresult=awaitclient.discover('Tesla battery technology',{intent: 'recent breakthroughs in EV battery chemistry',});// With filtering and localizationconstresult=awaitclient.discover('sustainable fashion brands',{intent: 'eco-friendly clothing companies',filterKeywords: ['sustainability','eco-friendly','organic'],country: 'us',numResults: 10,});// Include full page contentconstresult=awaitclient.discover('python asyncio tutorial',{includeContent: true,numResults: 3,});// Manual trigger/poll/fetchconstjob=awaitclient.discoverTrigger('market research SaaS',{intent: 'competitor pricing strategies',});awaitjob.wait({timeout: 60_000});constdata=awaitjob.fetch();

Scraper Studio

Trigger and fetch results from your custom scrapers built in Scraper Studio.

// Orchestrated — trigger + poll + return resultsconstresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: {url: 'https://example.com/product/1'},});// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }// Multiple inputs (processed sequentially)constresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: [{url: 'https://example.com/product/1'},{url: 'https://example.com/product/2'},],});// Manual control — trigger, then poll yourselfconstjob=awaitclient.scraperStudio.trigger('c_your_collector_id',{url: 'https://example.com/product/1',});constdata=awaitjob.waitAndFetch();// Check job status (by job ID from the dashboard)conststatus=awaitclient.scraperStudio.status('j_abc123');console.log(status.status);// 'queued' | 'running' | 'done' | 'failed'

Browser API

Build CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers. Credentials come from browserUsername/browserPassword options or BRIGHTDATA_BROWSERAPI_USERNAME/BRIGHTDATA_BROWSERAPI_PASSWORD env vars.

// Get a connection URLconsturl=client.browser.getConnectUrl();// Geo-target the browser with a 2-letter country codeconstusUrl=client.browser.getConnectUrl({country: 'us'});// Connect with Playwrightimport{chromium}from'playwright';constbrowser=awaitchromium.connectOverCDP(url);constpage=awaitbrowser.newPage();awaitpage.goto('https://example.com');consthtml=awaitpage.content();awaitbrowser.close();

Datasets

Access 126 pre-built datasets for querying and downloading structured data snapshots.

constds=client.datasets;// List all datasets available on your accountconstlist=awaitds.list();// Get field metadata for a datasetconstmeta=awaitds.instagramProfiles.getMetadata();console.log(meta.fields);// [{ name, type, description }, ...]// Query a dataset (triggers a snapshot)constsnapshotId=awaitds.instagramProfiles.query({url: 'https://www.instagram.com/natgeo/'},{records_limit: 10},);// Check snapshot statusconststatus=awaitds.instagramProfiles.getStatus(snapshotId);console.log(status.status);// 'running' | 'ready' | ...// Download when readyconstrows=awaitds.instagramProfiles.download(snapshotId);

Available datasets:

PlatformDatasets
LinkedInlinkedinProfiles, linkedinCompanies
AmazonamazonProducts, amazonReviews, amazonSellers, amazonBestSellers, amazonProductsSearch, amazonProductsGlobal, amazonWalmart
InstagraminstagramProfiles, instagramPosts, instagramComments, instagramReels
TikToktiktokProfiles, tiktokPosts, tiktokComments, tiktokShop
X/TwitterxTwitterPosts, xTwitterProfiles

Saving results

constdata=awaitclient.scrapeUrl('https://example.com');constfilePath=awaitclient.saveResults(data,{filename: 'results.json',format: 'json',});console.log(`Saved to: ${filePath}`);

Configuration

Runtime support

Node.js (>= 20) is the supported and tested runtime. The SDK also runs under Bun without crashing, but with a real caveat: Bun's bundled undici provides only a bare-bones Agent (no compose(), no close(), no custom dispatch), and Bun's request()/stream() ignore the dispatcher option entirely, routing through Bun's own native HTTP client instead. In practice this means requests still succeed under Bun, but none of Transport's tuning — connection pooling, keep-alive, custom timeouts, automatic retry on 429/500/502/503/504, and DNS caching — has any effect there; Bun's own defaults apply instead. The SDK detects the missing capabilities automatically (never crashes construction or close()), rather than failing.

API Token

Get your API token from Bright Data Control Panel.

Already logged in with the CLI? The SDK works with no configuration. If you've run brightdata login with the Bright Data CLI, the SDK automatically picks up those stored credentials. The token is resolved in this order:

  1. apiKey passed to new bdclient({ apiKey })
  2. BRIGHTDATA_API_TOKEN (or BRIGHTDATA_API_KEY) environment variable
  3. Credentials stored by the CLI (brightdata login)

If none are found, the client throws with instructions to log in or set a token.

Environment Variables

BRIGHTDATA_API_TOKEN=your_api_token# BRIGHTDATA_API_KEY also acceptedBRIGHTDATA_WEB_UNLOCKER_ZONE=your_web_unlocker_zone# OptionalBRIGHTDATA_SERP_ZONE=your_serp_zone# OptionalBRIGHTDATA_BROWSERAPI_USERNAME=your_browser_username# Optional, for Browser APIBRIGHTDATA_BROWSERAPI_PASSWORD=your_browser_password# Optional, for Browser APIBRIGHTDATA_VERBOSE=1# Optional, enable verbose logging

Tip: When loading these from a .env file with node --env-file=.env, note that variables already set in your shell take precedence over the file.

Client Options

constclient=newbdclient({apiKey: 'string',// API token (or use BRIGHTDATA_API_TOKEN env var)timeout: 120000,// Request timeout in ms (1000–300000)autoCreateZones: true,// Auto-create zones if they don't existwebUnlockerZone: 'string',// Custom web unlocker zone nameserpZone: 'string',// Custom SERP zone namelogLevel: 'INFO',// 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'structuredLogging: true,// Use structured JSON loggingverbose: false,// Enable verbose loggingrateLimit: 0,// Max requests per period (0 = unlimited)ratePeriod: 1000,// Rate limit period in ms});

Resource Cleanup

The client maintains HTTP connections. Always close when done:

awaitclient.close();// Or use Symbol.asyncDispose (TypeScript 5.2+)awaitusingclient=newbdclient();

Constants

ConstantDefaultDescription
DEFAULT_CONCURRENCY10Max parallel tasks
DEFAULT_TIMEOUT120000Request timeout (milliseconds)
MAX_RETRIES3Retry attempts on failure
RETRY_BACKOFF_FACTOR1.5Exponential backoff multiplier

Zone Management

constzones=awaitclient.listZones();console.log(`Found ${zones.length} zones`);

Subpath Exports

For tree-shaking or importing only what you need:

import{ScrapeRouter,LinkedinAPI}from'@brightdata/sdk/scrapers';import{SearchRouter}from'@brightdata/sdk/search';import{DatasetsClient,BaseDataset}from'@brightdata/sdk/datasets';

Error Handling

The SDK exports typed error classes that extend BRDError:

import{bdclient,ValidationError,AuthenticationError,BRDError}from'@brightdata/sdk';try{constresult=awaitclient.scrapeUrl('https://example.com');}catch(error){if(errorinstanceofValidationError){console.error('Invalid input:',error.message);}elseif(errorinstanceofAuthenticationError){console.error('Auth failed:',error.message);}elseif(errorinstanceofBRDError){console.error('SDK error:',error.message);}}

Error types:ValidationError, AuthenticationError, ZoneError, NetworkError, NetworkTimeoutError, TimeoutError, APIError, DataNotReadyError, FSError

Troubleshooting

Windows & corporate networks

ProblemFix
npm.ps1 cannot be loaded because running scripts is disabled (PowerShell)Use cmd instead of PowerShell, or run npm.cmd <command>, or run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. If overridden by Group Policy, contact your IT team.
SELF_SIGNED_CERT_IN_CHAIN during npm installYour network uses SSL inspection. Point npm to your corporate root certificate: npm config set cafile "C:\path\to\corporate-root.cer"
Certificate errors at runtimeSet the env variable NODE_EXTRA_CA_CERTS=C:\path\to\corporate-root.cer so Node trusts your corporate certificate.

AuthenticationError: invalid API key

If you get this error, check the following in order:

  1. Verify the token itself works, outside the SDK:
    curl -H "Authorization: Bearer YOUR_TOKEN" https://api.brightdata.com/zone/get_active_zones
    If this fails, generate a new API key with admin permissions in the control panel. Note the SDK needs an account-level API token — not a zone password.
  2. Check for shell overrides. Environment variables set in your shell take precedence over .env files loaded with node --env-file=.env. Run set BRIGHTDATA (Windows) or env | grep BRIGHTDATA (macOS/Linux) and clear any leftover values.
  3. Check your .env file: no quotes, no spaces around =, no trailing whitespace, and the token copied exactly (including dashes). Prefer LF line endings.
  4. Print what actually loaded:
    console.log(JSON.stringify(process.env.BRIGHTDATA_API_TOKEN));
    Hidden characters like \r will be visible in the output.

Support

For any issues, contact Bright Data support, or open an issue in this repository.

License

This project is licensed under the MIT License.

About

Bright Data's JS SDK, use it to call bright data's scrape and search tools. bypass any Bot-detection or Captcha and extract data from the web.

Topics

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

sdk-banner(1)

Bright Data JavaScript SDK providing easy and scalable methods for scraping, web search, datasets, and more.

Installation @latest

npm install @brightdata/sdk

Quick start

1. Signup and get your API token

2. Initialize the client

import{bdclient}from'@brightdata/sdk';constclient=newbdclient({apiKey: '[your_api_token]',// or set BRIGHTDATA_API_TOKEN env variable});

3. Launch your first request

// Scrape a webpageconsthtml=awaitclient.scrapeUrl('https://example.com');console.log(html);// Search the webconstresults=awaitclient.search.google('pizza restaurants',{country: 'us'});console.log(results);

Don't forget to close when done:

awaitclient.close();

Features

  • Web Scraping — Scrape any website using anti-bot detection bypass and proxy support
  • Search Engine Results — Google, Bing, and Yandex search with batch support
  • Platform Scrapers — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
  • Crawl API — Crawl any URL(s) and get every output format (markdown, HTML, text) bundled per page
  • Discover API — AI-powered web search with intent-based relevance ranking
  • Scraper Studio — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
  • Browser API — CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers
  • Datasets — Access 126 pre-built datasets across dozens of platforms with query/download support
  • Parallel Processing — Concurrent processing for multiple URLs or queries
  • Robust Error Handling — Typed error classes with retry logic
  • Zone Management — Automatic zone creation and management
  • Multiple Output Formats — HTML, JSON, Markdown, and screenshots
  • Dual Build — Both ESM and CommonJS supported
  • TypeScript — Fully typed API with overloaded signatures
  • Subpath Exports — Tree-shakeable imports via @brightdata/sdk/scrapers, @brightdata/sdk/search, @brightdata/sdk/datasets

Usage

Scrape websites

// Single URL — returns HTML string by defaultconsthtml=awaitclient.scrapeUrl('https://example.com');// Multiple URLs (parallel processing)constresults=awaitclient.scrapeUrl(['https://example1.com','https://example2.com',]);// Get markdown contentconstmd=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'markdown',});// Get structured JSONconstdata=awaitclient.scrapeUrl('https://example.com',{format: 'json',});// Take a screenshotconstscreenshot=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'screenshot',});// Full optionsconstresult=awaitclient.scrapeUrl('https://example.com',{format: 'raw',// 'raw' (default) or 'json'dataFormat: 'html',// 'html' (default), 'markdown' (alias: 'md'), 'screenshot'country: 'gb',// two-letter country codemethod: 'GET',// HTTP method});

Search engines

// Google searchconstresults=awaitclient.search.google('pizza restaurants');// Bing searchconstresults=awaitclient.search.bing('pizza restaurants');// Yandex searchconstresults=awaitclient.search.yandex('pizza restaurants');// Batch search (parallel)constresults=awaitclient.search.google(['pizza','sushi','tacos']);// With optionsconstresults=awaitclient.search.google('pizza',{country: 'gb',format: 'json',});

Note: If country is not specified, requests exit through an arbitrary proxy location, so results may be geo-located to an unexpected country. Always pass country when you need consistent, localized results.

Platform scrapers

Collect structured data from popular platforms. Each platform supports sync collection (collect*) and async orchestrated scraping (trigger, poll, download).

// LinkedIn profilesconstdata=awaitclient.scrape.linkedin.collectProfiles(['https://www.linkedin.com/in/satyanadella/'],{format: 'json'},);// Amazon productsconstdata=awaitclient.scrape.amazon.collectProducts(['https://www.amazon.com/dp/B0D77BX8Y4'],{format: 'json'},);// Instagram profilesconstdata=awaitclient.scrape.instagram.collectProfiles(['https://www.instagram.com/natgeo/'],{format: 'json'},);// TikTok profilesconstdata=awaitclient.scrape.tiktok.collectProfiles(['https://www.tiktok.com/@tiktok'],{format: 'json'},);// YouTube videosconstdata=awaitclient.scrape.youtube.collectVideos(['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],{format: 'json'},);// Reddit postsconstdata=awaitclient.scrape.reddit.collectPosts(['https://www.reddit.com/r/technology/top/'],{format: 'json'},);

Orchestrated scraping (async trigger → poll → download):

constresult=awaitclient.scrape.linkedin.profiles(['https://www.linkedin.com/in/satyanadella/'],{pollInterval: 5000,pollTimeout: 180_000},);console.log(result.data);// structured dataconsole.log(result.status);// 'ready'console.log(result.rowCount);

Available platforms:linkedin, amazon, instagram, tiktok, youtube, reddit, facebook, pinterest, chatGPT, digikey, perplexity

Crawl API

Crawl one or more URLs and get every output format (markdown, HTML, text) bundled per page.

// Sync — single round-tripconstresult=awaitclient.crawler.crawl('https://example.com');console.log(result.data[0].markdown);// Batchconstresult=awaitclient.crawler.crawl(['https://example.com','https://example.com/about',]);console.log(`${result.pageCount} pages`);// Async — trigger, poll, downloadconstjob=awaitclient.crawler.trigger('https://example.com');conststatus=awaitclient.crawler.status(job.snapshotId);constresult=awaitclient.crawler.download(job.snapshotId);

Discover API

AI-powered web search with relevance ranking based on intent.

discover() resolves to a DiscoverResult wrapper (not a bare array). The items are on result.data (or its alias result.results), and the result is iterable. On failure result.success is false, result.error carries the reason, and result.data / result.results stay an empty array — so iterating never throws.

// Basic searchconstresult=awaitclient.discover('artificial intelligence trends 2026');if(!result.success){console.error('discover failed:',result.error);}else{console.log(result.results);// [{ link, title, description, relevance_score }, ...]for(constitemofresult){console.log(`[${item.relevance_score}] ${item.title}`);}}// With intent for semantic rankingconstresult=awaitclient.discover('Tesla battery technology',{intent: 'recent breakthroughs in EV battery chemistry',});// With filtering and localizationconstresult=awaitclient.discover('sustainable fashion brands',{intent: 'eco-friendly clothing companies',filterKeywords: ['sustainability','eco-friendly','organic'],country: 'us',numResults: 10,});// Include full page contentconstresult=awaitclient.discover('python asyncio tutorial',{includeContent: true,numResults: 3,});// Manual trigger/poll/fetchconstjob=awaitclient.discoverTrigger('market research SaaS',{intent: 'competitor pricing strategies',});awaitjob.wait({timeout: 60_000});constdata=awaitjob.fetch();

Scraper Studio

Trigger and fetch results from your custom scrapers built in Scraper Studio.

// Orchestrated — trigger + poll + return resultsconstresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: {url: 'https://example.com/product/1'},});// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }// Multiple inputs (processed sequentially)constresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: [{url: 'https://example.com/product/1'},{url: 'https://example.com/product/2'},],});// Manual control — trigger, then poll yourselfconstjob=awaitclient.scraperStudio.trigger('c_your_collector_id',{url: 'https://example.com/product/1',});constdata=awaitjob.waitAndFetch();// Check job status (by job ID from the dashboard)conststatus=awaitclient.scraperStudio.status('j_abc123');console.log(status.status);// 'queued' | 'running' | 'done' | 'failed'

Browser API

Build CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers. Credentials come from browserUsername/browserPassword options or BRIGHTDATA_BROWSERAPI_USERNAME/BRIGHTDATA_BROWSERAPI_PASSWORD env vars.

// Get a connection URLconsturl=client.browser.getConnectUrl();// Geo-target the browser with a 2-letter country codeconstusUrl=client.browser.getConnectUrl({country: 'us'});// Connect with Playwrightimport{chromium}from'playwright';constbrowser=awaitchromium.connectOverCDP(url);constpage=awaitbrowser.newPage();awaitpage.goto('https://example.com');consthtml=awaitpage.content();awaitbrowser.close();

Datasets

Access 126 pre-built datasets for querying and downloading structured data snapshots.

constds=client.datasets;// List all datasets available on your accountconstlist=awaitds.list();// Get field metadata for a datasetconstmeta=awaitds.instagramProfiles.getMetadata();console.log(meta.fields);// [{ name, type, description }, ...]// Query a dataset (triggers a snapshot)constsnapshotId=awaitds.instagramProfiles.query({url: 'https://www.instagram.com/natgeo/'},{records_limit: 10},);// Check snapshot statusconststatus=awaitds.instagramProfiles.getStatus(snapshotId);console.log(status.status);// 'running' | 'ready' | ...// Download when readyconstrows=awaitds.instagramProfiles.download(snapshotId);

Available datasets:

PlatformDatasets
LinkedInlinkedinProfiles, linkedinCompanies
AmazonamazonProducts, amazonReviews, amazonSellers, amazonBestSellers, amazonProductsSearch, amazonProductsGlobal, amazonWalmart
InstagraminstagramProfiles, instagramPosts, instagramComments, instagramReels
TikToktiktokProfiles, tiktokPosts, tiktokComments, tiktokShop
X/TwitterxTwitterPosts, xTwitterProfiles

Saving results

constdata=awaitclient.scrapeUrl('https://example.com');constfilePath=awaitclient.saveResults(data,{filename: 'results.json',format: 'json',});console.log(`Saved to: ${filePath}`);

Configuration

Runtime support

Node.js (>= 20) is the supported and tested runtime. The SDK also runs under Bun without crashing, but with a real caveat: Bun's bundled undici provides only a bare-bones Agent (no compose(), no close(), no custom dispatch), and Bun's request()/stream() ignore the dispatcher option entirely, routing through Bun's own native HTTP client instead. In practice this means requests still succeed under Bun, but none of Transport's tuning — connection pooling, keep-alive, custom timeouts, automatic retry on 429/500/502/503/504, and DNS caching — has any effect there; Bun's own defaults apply instead. The SDK detects the missing capabilities automatically (never crashes construction or close()), rather than failing.

API Token

Get your API token from Bright Data Control Panel.

Already logged in with the CLI? The SDK works with no configuration. If you've run brightdata login with the Bright Data CLI, the SDK automatically picks up those stored credentials. The token is resolved in this order:

  1. apiKey passed to new bdclient({ apiKey })
  2. BRIGHTDATA_API_TOKEN (or BRIGHTDATA_API_KEY) environment variable
  3. Credentials stored by the CLI (brightdata login)

If none are found, the client throws with instructions to log in or set a token.

Environment Variables

BRIGHTDATA_API_TOKEN=your_api_token# BRIGHTDATA_API_KEY also acceptedBRIGHTDATA_WEB_UNLOCKER_ZONE=your_web_unlocker_zone# OptionalBRIGHTDATA_SERP_ZONE=your_serp_zone# OptionalBRIGHTDATA_BROWSERAPI_USERNAME=your_browser_username# Optional, for Browser APIBRIGHTDATA_BROWSERAPI_PASSWORD=your_browser_password# Optional, for Browser APIBRIGHTDATA_VERBOSE=1# Optional, enable verbose logging

Tip: When loading these from a .env file with node --env-file=.env, note that variables already set in your shell take precedence over the file.

Client Options

constclient=newbdclient({apiKey: 'string',// API token (or use BRIGHTDATA_API_TOKEN env var)timeout: 120000,// Request timeout in ms (1000–300000)autoCreateZones: true,// Auto-create zones if they don't existwebUnlockerZone: 'string',// Custom web unlocker zone nameserpZone: 'string',// Custom SERP zone namelogLevel: 'INFO',// 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'structuredLogging: true,// Use structured JSON loggingverbose: false,// Enable verbose loggingrateLimit: 0,// Max requests per period (0 = unlimited)ratePeriod: 1000,// Rate limit period in ms});

Resource Cleanup

The client maintains HTTP connections. Always close when done:

awaitclient.close();// Or use Symbol.asyncDispose (TypeScript 5.2+)awaitusingclient=newbdclient();

Constants

ConstantDefaultDescription
DEFAULT_CONCURRENCY10Max parallel tasks
DEFAULT_TIMEOUT120000Request timeout (milliseconds)
MAX_RETRIES3Retry attempts on failure
RETRY_BACKOFF_FACTOR1.5Exponential backoff multiplier

Zone Management

constzones=awaitclient.listZones();console.log(`Found ${zones.length} zones`);

Subpath Exports

For tree-shaking or importing only what you need:

import{ScrapeRouter,LinkedinAPI}from'@brightdata/sdk/scrapers';import{SearchRouter}from'@brightdata/sdk/search';import{DatasetsClient,BaseDataset}from'@brightdata/sdk/datasets';

Error Handling

The SDK exports typed error classes that extend BRDError:

import{bdclient,ValidationError,AuthenticationError,BRDError}from'@brightdata/sdk';try{constresult=awaitclient.scrapeUrl('https://example.com');}catch(error){if(errorinstanceofValidationError){console.error('Invalid input:',error.message);}elseif(errorinstanceofAuthenticationError){console.error('Auth failed:',error.message);}elseif(errorinstanceofBRDError){console.error('SDK error:',error.message);}}

Error types:ValidationError, AuthenticationError, ZoneError, NetworkError, NetworkTimeoutError, TimeoutError, APIError, DataNotReadyError, FSError

Troubleshooting

Windows & corporate networks

ProblemFix
npm.ps1 cannot be loaded because running scripts is disabled (PowerShell)Use cmd instead of PowerShell, or run npm.cmd <command>, or run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. If overridden by Group Policy, contact your IT team.
SELF_SIGNED_CERT_IN_CHAIN during npm installYour network uses SSL inspection. Point npm to your corporate root certificate: npm config set cafile "C:\path\to\corporate-root.cer"
Certificate errors at runtimeSet the env variable NODE_EXTRA_CA_CERTS=C:\path\to\corporate-root.cer so Node trusts your corporate certificate.

AuthenticationError: invalid API key

If you get this error, check the following in order:

  1. Verify the token itself works, outside the SDK:
    curl -H "Authorization: Bearer YOUR_TOKEN" https://api.brightdata.com/zone/get_active_zones
    If this fails, generate a new API key with admin permissions in the control panel. Note the SDK needs an account-level API token — not a zone password.
  2. Check for shell overrides. Environment variables set in your shell take precedence over .env files loaded with node --env-file=.env. Run set BRIGHTDATA (Windows) or env | grep BRIGHTDATA (macOS/Linux) and clear any leftover values.
  3. Check your .env file: no quotes, no spaces around =, no trailing whitespace, and the token copied exactly (including dashes). Prefer LF line endings.
  4. Print what actually loaded:
    console.log(JSON.stringify(process.env.BRIGHTDATA_API_TOKEN));
    Hidden characters like \r will be visible in the output.

Support

For any issues, contact Bright Data support, or open an issue in this repository.

License

This project is licensed under the MIT License.

About

Bright Data's JS SDK, use it to call bright data's scrape and search tools. bypass any Bot-detection or Captcha and extract data from the web.

Topics

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

sdk-banner(1)

Bright Data JavaScript SDK providing easy and scalable methods for scraping, web search, datasets, and more.

Installation @latest

npm install @brightdata/sdk

Quick start

1. Signup and get your API token

2. Initialize the client

import{bdclient}from'@brightdata/sdk';constclient=newbdclient({apiKey: '[your_api_token]',// or set BRIGHTDATA_API_TOKEN env variable});

3. Launch your first request

// Scrape a webpageconsthtml=awaitclient.scrapeUrl('https://example.com');console.log(html);// Search the webconstresults=awaitclient.search.google('pizza restaurants',{country: 'us'});console.log(results);

Don't forget to close when done:

awaitclient.close();

Features

  • Web Scraping — Scrape any website using anti-bot detection bypass and proxy support
  • Search Engine Results — Google, Bing, and Yandex search with batch support
  • Platform Scrapers — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
  • Crawl API — Crawl any URL(s) and get every output format (markdown, HTML, text) bundled per page
  • Discover API — AI-powered web search with intent-based relevance ranking
  • Scraper Studio — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
  • Browser API — CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers
  • Datasets — Access 126 pre-built datasets across dozens of platforms with query/download support
  • Parallel Processing — Concurrent processing for multiple URLs or queries
  • Robust Error Handling — Typed error classes with retry logic
  • Zone Management — Automatic zone creation and management
  • Multiple Output Formats — HTML, JSON, Markdown, and screenshots
  • Dual Build — Both ESM and CommonJS supported
  • TypeScript — Fully typed API with overloaded signatures
  • Subpath Exports — Tree-shakeable imports via @brightdata/sdk/scrapers, @brightdata/sdk/search, @brightdata/sdk/datasets

Usage

Scrape websites

// Single URL — returns HTML string by defaultconsthtml=awaitclient.scrapeUrl('https://example.com');// Multiple URLs (parallel processing)constresults=awaitclient.scrapeUrl(['https://example1.com','https://example2.com',]);// Get markdown contentconstmd=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'markdown',});// Get structured JSONconstdata=awaitclient.scrapeUrl('https://example.com',{format: 'json',});// Take a screenshotconstscreenshot=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'screenshot',});// Full optionsconstresult=awaitclient.scrapeUrl('https://example.com',{format: 'raw',// 'raw' (default) or 'json'dataFormat: 'html',// 'html' (default), 'markdown' (alias: 'md'), 'screenshot'country: 'gb',// two-letter country codemethod: 'GET',// HTTP method});

Search engines

// Google searchconstresults=awaitclient.search.google('pizza restaurants');// Bing searchconstresults=awaitclient.search.bing('pizza restaurants');// Yandex searchconstresults=awaitclient.search.yandex('pizza restaurants');// Batch search (parallel)constresults=awaitclient.search.google(['pizza','sushi','tacos']);// With optionsconstresults=awaitclient.search.google('pizza',{country: 'gb',format: 'json',});

Note: If country is not specified, requests exit through an arbitrary proxy location, so results may be geo-located to an unexpected country. Always pass country when you need consistent, localized results.

Platform scrapers

Collect structured data from popular platforms. Each platform supports sync collection (collect*) and async orchestrated scraping (trigger, poll, download).

// LinkedIn profilesconstdata=awaitclient.scrape.linkedin.collectProfiles(['https://www.linkedin.com/in/satyanadella/'],{format: 'json'},);// Amazon productsconstdata=awaitclient.scrape.amazon.collectProducts(['https://www.amazon.com/dp/B0D77BX8Y4'],{format: 'json'},);// Instagram profilesconstdata=awaitclient.scrape.instagram.collectProfiles(['https://www.instagram.com/natgeo/'],{format: 'json'},);// TikTok profilesconstdata=awaitclient.scrape.tiktok.collectProfiles(['https://www.tiktok.com/@tiktok'],{format: 'json'},);// YouTube videosconstdata=awaitclient.scrape.youtube.collectVideos(['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],{format: 'json'},);// Reddit postsconstdata=awaitclient.scrape.reddit.collectPosts(['https://www.reddit.com/r/technology/top/'],{format: 'json'},);

Orchestrated scraping (async trigger → poll → download):

constresult=awaitclient.scrape.linkedin.profiles(['https://www.linkedin.com/in/satyanadella/'],{pollInterval: 5000,pollTimeout: 180_000},);console.log(result.data);// structured dataconsole.log(result.status);// 'ready'console.log(result.rowCount);

Available platforms:linkedin, amazon, instagram, tiktok, youtube, reddit, facebook, pinterest, chatGPT, digikey, perplexity

Crawl API

Crawl one or more URLs and get every output format (markdown, HTML, text) bundled per page.

// Sync — single round-tripconstresult=awaitclient.crawler.crawl('https://example.com');console.log(result.data[0].markdown);// Batchconstresult=awaitclient.crawler.crawl(['https://example.com','https://example.com/about',]);console.log(`${result.pageCount} pages`);// Async — trigger, poll, downloadconstjob=awaitclient.crawler.trigger('https://example.com');conststatus=awaitclient.crawler.status(job.snapshotId);constresult=awaitclient.crawler.download(job.snapshotId);

Discover API

AI-powered web search with relevance ranking based on intent.

discover() resolves to a DiscoverResult wrapper (not a bare array). The items are on result.data (or its alias result.results), and the result is iterable. On failure result.success is false, result.error carries the reason, and result.data / result.results stay an empty array — so iterating never throws.

// Basic searchconstresult=awaitclient.discover('artificial intelligence trends 2026');if(!result.success){console.error('discover failed:',result.error);}else{console.log(result.results);// [{ link, title, description, relevance_score }, ...]for(constitemofresult){console.log(`[${item.relevance_score}] ${item.title}`);}}// With intent for semantic rankingconstresult=awaitclient.discover('Tesla battery technology',{intent: 'recent breakthroughs in EV battery chemistry',});// With filtering and localizationconstresult=awaitclient.discover('sustainable fashion brands',{intent: 'eco-friendly clothing companies',filterKeywords: ['sustainability','eco-friendly','organic'],country: 'us',numResults: 10,});// Include full page contentconstresult=awaitclient.discover('python asyncio tutorial',{includeContent: true,numResults: 3,});// Manual trigger/poll/fetchconstjob=awaitclient.discoverTrigger('market research SaaS',{intent: 'competitor pricing strategies',});awaitjob.wait({timeout: 60_000});constdata=awaitjob.fetch();

Scraper Studio

Trigger and fetch results from your custom scrapers built in Scraper Studio.

// Orchestrated — trigger + poll + return resultsconstresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: {url: 'https://example.com/product/1'},});// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }// Multiple inputs (processed sequentially)constresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: [{url: 'https://example.com/product/1'},{url: 'https://example.com/product/2'},],});// Manual control — trigger, then poll yourselfconstjob=awaitclient.scraperStudio.trigger('c_your_collector_id',{url: 'https://example.com/product/1',});constdata=awaitjob.waitAndFetch();// Check job status (by job ID from the dashboard)conststatus=awaitclient.scraperStudio.status('j_abc123');console.log(status.status);// 'queued' | 'running' | 'done' | 'failed'

Browser API

Build CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers. Credentials come from browserUsername/browserPassword options or BRIGHTDATA_BROWSERAPI_USERNAME/BRIGHTDATA_BROWSERAPI_PASSWORD env vars.

// Get a connection URLconsturl=client.browser.getConnectUrl();// Geo-target the browser with a 2-letter country codeconstusUrl=client.browser.getConnectUrl({country: 'us'});// Connect with Playwrightimport{chromium}from'playwright';constbrowser=awaitchromium.connectOverCDP(url);constpage=awaitbrowser.newPage();awaitpage.goto('https://example.com');consthtml=awaitpage.content();awaitbrowser.close();

Datasets

Access 126 pre-built datasets for querying and downloading structured data snapshots.

constds=client.datasets;// List all datasets available on your accountconstlist=awaitds.list();// Get field metadata for a datasetconstmeta=awaitds.instagramProfiles.getMetadata();console.log(meta.fields);// [{ name, type, description }, ...]// Query a dataset (triggers a snapshot)constsnapshotId=awaitds.instagramProfiles.query({url: 'https://www.instagram.com/natgeo/'},{records_limit: 10},);// Check snapshot statusconststatus=awaitds.instagramProfiles.getStatus(snapshotId);console.log(status.status);// 'running' | 'ready' | ...// Download when readyconstrows=awaitds.instagramProfiles.download(snapshotId);

Available datasets:

PlatformDatasets
LinkedInlinkedinProfiles, linkedinCompanies
AmazonamazonProducts, amazonReviews, amazonSellers, amazonBestSellers, amazonProductsSearch, amazonProductsGlobal, amazonWalmart
InstagraminstagramProfiles, instagramPosts, instagramComments, instagramReels
TikToktiktokProfiles, tiktokPosts, tiktokComments, tiktokShop
X/TwitterxTwitterPosts, xTwitterProfiles

Saving results

constdata=awaitclient.scrapeUrl('https://example.com');constfilePath=awaitclient.saveResults(data,{filename: 'results.json',format: 'json',});console.log(`Saved to: ${filePath}`);

Configuration

Runtime support

Node.js (>= 20) is the supported and tested runtime. The SDK also runs under Bun without crashing, but with a real caveat: Bun's bundled undici provides only a bare-bones Agent (no compose(), no close(), no custom dispatch), and Bun's request()/stream() ignore the dispatcher option entirely, routing through Bun's own native HTTP client instead. In practice this means requests still succeed under Bun, but none of Transport's tuning — connection pooling, keep-alive, custom timeouts, automatic retry on 429/500/502/503/504, and DNS caching — has any effect there; Bun's own defaults apply instead. The SDK detects the missing capabilities automatically (never crashes construction or close()), rather than failing.

API Token

Get your API token from Bright Data Control Panel.

Already logged in with the CLI? The SDK works with no configuration. If you've run brightdata login with the Bright Data CLI, the SDK automatically picks up those stored credentials. The token is resolved in this order:

  1. apiKey passed to new bdclient({ apiKey })
  2. BRIGHTDATA_API_TOKEN (or BRIGHTDATA_API_KEY) environment variable
  3. Credentials stored by the CLI (brightdata login)

If none are found, the client throws with instructions to log in or set a token.

Environment Variables

BRIGHTDATA_API_TOKEN=your_api_token# BRIGHTDATA_API_KEY also acceptedBRIGHTDATA_WEB_UNLOCKER_ZONE=your_web_unlocker_zone# OptionalBRIGHTDATA_SERP_ZONE=your_serp_zone# OptionalBRIGHTDATA_BROWSERAPI_USERNAME=your_browser_username# Optional, for Browser APIBRIGHTDATA_BROWSERAPI_PASSWORD=your_browser_password# Optional, for Browser APIBRIGHTDATA_VERBOSE=1# Optional, enable verbose logging

Tip: When loading these from a .env file with node --env-file=.env, note that variables already set in your shell take precedence over the file.

Client Options

constclient=newbdclient({apiKey: 'string',// API token (or use BRIGHTDATA_API_TOKEN env var)timeout: 120000,// Request timeout in ms (1000–300000)autoCreateZones: true,// Auto-create zones if they don't existwebUnlockerZone: 'string',// Custom web unlocker zone nameserpZone: 'string',// Custom SERP zone namelogLevel: 'INFO',// 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'structuredLogging: true,// Use structured JSON loggingverbose: false,// Enable verbose loggingrateLimit: 0,// Max requests per period (0 = unlimited)ratePeriod: 1000,// Rate limit period in ms});

Resource Cleanup

The client maintains HTTP connections. Always close when done:

awaitclient.close();// Or use Symbol.asyncDispose (TypeScript 5.2+)awaitusingclient=newbdclient();

Constants

ConstantDefaultDescription
DEFAULT_CONCURRENCY10Max parallel tasks
DEFAULT_TIMEOUT120000Request timeout (milliseconds)
MAX_RETRIES3Retry attempts on failure
RETRY_BACKOFF_FACTOR1.5Exponential backoff multiplier

Zone Management

constzones=awaitclient.listZones();console.log(`Found ${zones.length} zones`);

Subpath Exports

For tree-shaking or importing only what you need:

import{ScrapeRouter,LinkedinAPI}from'@brightdata/sdk/scrapers';import{SearchRouter}from'@brightdata/sdk/search';import{DatasetsClient,BaseDataset}from'@brightdata/sdk/datasets';

Error Handling

The SDK exports typed error classes that extend BRDError:

import{bdclient,ValidationError,AuthenticationError,BRDError}from'@brightdata/sdk';try{constresult=awaitclient.scrapeUrl('https://example.com');}catch(error){if(errorinstanceofValidationError){console.error('Invalid input:',error.message);}elseif(errorinstanceofAuthenticationError){console.error('Auth failed:',error.message);}elseif(errorinstanceofBRDError){console.error('SDK error:',error.message);}}

Error types:ValidationError, AuthenticationError, ZoneError, NetworkError, NetworkTimeoutError, TimeoutError, APIError, DataNotReadyError, FSError

Troubleshooting

Windows & corporate networks

ProblemFix
npm.ps1 cannot be loaded because running scripts is disabled (PowerShell)Use cmd instead of PowerShell, or run npm.cmd <command>, or run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. If overridden by Group Policy, contact your IT team.
SELF_SIGNED_CERT_IN_CHAIN during npm installYour network uses SSL inspection. Point npm to your corporate root certificate: npm config set cafile "C:\path\to\corporate-root.cer"
Certificate errors at runtimeSet the env variable NODE_EXTRA_CA_CERTS=C:\path\to\corporate-root.cer so Node trusts your corporate certificate.

AuthenticationError: invalid API key

If you get this error, check the following in order:

  1. Verify the token itself works, outside the SDK:
    curl -H "Authorization: Bearer YOUR_TOKEN" https://api.brightdata.com/zone/get_active_zones
    If this fails, generate a new API key with admin permissions in the control panel. Note the SDK needs an account-level API token — not a zone password.
  2. Check for shell overrides. Environment variables set in your shell take precedence over .env files loaded with node --env-file=.env. Run set BRIGHTDATA (Windows) or env | grep BRIGHTDATA (macOS/Linux) and clear any leftover values.
  3. Check your .env file: no quotes, no spaces around =, no trailing whitespace, and the token copied exactly (including dashes). Prefer LF line endings.
  4. Print what actually loaded:
    console.log(JSON.stringify(process.env.BRIGHTDATA_API_TOKEN));
    Hidden characters like \r will be visible in the output.

Support

For any issues, contact Bright Data support, or open an issue in this repository.

License

This project is licensed under the MIT License.

About

Bright Data's JS SDK, use it to call bright data's scrape and search tools. bypass any Bot-detection or Captcha and extract data from the web.

Topics

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

sdk-banner(1)

Bright Data JavaScript SDK providing easy and scalable methods for scraping, web search, datasets, and more.

Installation @latest

npm install @brightdata/sdk

Quick start

1. Signup and get your API token

2. Initialize the client

import{bdclient}from'@brightdata/sdk';constclient=newbdclient({apiKey: '[your_api_token]',// or set BRIGHTDATA_API_TOKEN env variable});

3. Launch your first request

// Scrape a webpageconsthtml=awaitclient.scrapeUrl('https://example.com');console.log(html);// Search the webconstresults=awaitclient.search.google('pizza restaurants',{country: 'us'});console.log(results);

Don't forget to close when done:

awaitclient.close();

Features

  • Web Scraping — Scrape any website using anti-bot detection bypass and proxy support
  • Search Engine Results — Google, Bing, and Yandex search with batch support
  • Platform Scrapers — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
  • Crawl API — Crawl any URL(s) and get every output format (markdown, HTML, text) bundled per page
  • Discover API — AI-powered web search with intent-based relevance ranking
  • Scraper Studio — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
  • Browser API — CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers
  • Datasets — Access 126 pre-built datasets across dozens of platforms with query/download support
  • Parallel Processing — Concurrent processing for multiple URLs or queries
  • Robust Error Handling — Typed error classes with retry logic
  • Zone Management — Automatic zone creation and management
  • Multiple Output Formats — HTML, JSON, Markdown, and screenshots
  • Dual Build — Both ESM and CommonJS supported
  • TypeScript — Fully typed API with overloaded signatures
  • Subpath Exports — Tree-shakeable imports via @brightdata/sdk/scrapers, @brightdata/sdk/search, @brightdata/sdk/datasets

Usage

Scrape websites

// Single URL — returns HTML string by defaultconsthtml=awaitclient.scrapeUrl('https://example.com');// Multiple URLs (parallel processing)constresults=awaitclient.scrapeUrl(['https://example1.com','https://example2.com',]);// Get markdown contentconstmd=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'markdown',});// Get structured JSONconstdata=awaitclient.scrapeUrl('https://example.com',{format: 'json',});// Take a screenshotconstscreenshot=awaitclient.scrapeUrl('https://example.com',{dataFormat: 'screenshot',});// Full optionsconstresult=awaitclient.scrapeUrl('https://example.com',{format: 'raw',// 'raw' (default) or 'json'dataFormat: 'html',// 'html' (default), 'markdown' (alias: 'md'), 'screenshot'country: 'gb',// two-letter country codemethod: 'GET',// HTTP method});

Search engines

// Google searchconstresults=awaitclient.search.google('pizza restaurants');// Bing searchconstresults=awaitclient.search.bing('pizza restaurants');// Yandex searchconstresults=awaitclient.search.yandex('pizza restaurants');// Batch search (parallel)constresults=awaitclient.search.google(['pizza','sushi','tacos']);// With optionsconstresults=awaitclient.search.google('pizza',{country: 'gb',format: 'json',});

Note: If country is not specified, requests exit through an arbitrary proxy location, so results may be geo-located to an unexpected country. Always pass country when you need consistent, localized results.

Platform scrapers

Collect structured data from popular platforms. Each platform supports sync collection (collect*) and async orchestrated scraping (trigger, poll, download).

// LinkedIn profilesconstdata=awaitclient.scrape.linkedin.collectProfiles(['https://www.linkedin.com/in/satyanadella/'],{format: 'json'},);// Amazon productsconstdata=awaitclient.scrape.amazon.collectProducts(['https://www.amazon.com/dp/B0D77BX8Y4'],{format: 'json'},);// Instagram profilesconstdata=awaitclient.scrape.instagram.collectProfiles(['https://www.instagram.com/natgeo/'],{format: 'json'},);// TikTok profilesconstdata=awaitclient.scrape.tiktok.collectProfiles(['https://www.tiktok.com/@tiktok'],{format: 'json'},);// YouTube videosconstdata=awaitclient.scrape.youtube.collectVideos(['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],{format: 'json'},);// Reddit postsconstdata=awaitclient.scrape.reddit.collectPosts(['https://www.reddit.com/r/technology/top/'],{format: 'json'},);

Orchestrated scraping (async trigger → poll → download):

constresult=awaitclient.scrape.linkedin.profiles(['https://www.linkedin.com/in/satyanadella/'],{pollInterval: 5000,pollTimeout: 180_000},);console.log(result.data);// structured dataconsole.log(result.status);// 'ready'console.log(result.rowCount);

Available platforms:linkedin, amazon, instagram, tiktok, youtube, reddit, facebook, pinterest, chatGPT, digikey, perplexity

Crawl API

Crawl one or more URLs and get every output format (markdown, HTML, text) bundled per page.

// Sync — single round-tripconstresult=awaitclient.crawler.crawl('https://example.com');console.log(result.data[0].markdown);// Batchconstresult=awaitclient.crawler.crawl(['https://example.com','https://example.com/about',]);console.log(`${result.pageCount} pages`);// Async — trigger, poll, downloadconstjob=awaitclient.crawler.trigger('https://example.com');conststatus=awaitclient.crawler.status(job.snapshotId);constresult=awaitclient.crawler.download(job.snapshotId);

Discover API

AI-powered web search with relevance ranking based on intent.

discover() resolves to a DiscoverResult wrapper (not a bare array). The items are on result.data (or its alias result.results), and the result is iterable. On failure result.success is false, result.error carries the reason, and result.data / result.results stay an empty array — so iterating never throws.

// Basic searchconstresult=awaitclient.discover('artificial intelligence trends 2026');if(!result.success){console.error('discover failed:',result.error);}else{console.log(result.results);// [{ link, title, description, relevance_score }, ...]for(constitemofresult){console.log(`[${item.relevance_score}] ${item.title}`);}}// With intent for semantic rankingconstresult=awaitclient.discover('Tesla battery technology',{intent: 'recent breakthroughs in EV battery chemistry',});// With filtering and localizationconstresult=awaitclient.discover('sustainable fashion brands',{intent: 'eco-friendly clothing companies',filterKeywords: ['sustainability','eco-friendly','organic'],country: 'us',numResults: 10,});// Include full page contentconstresult=awaitclient.discover('python asyncio tutorial',{includeContent: true,numResults: 3,});// Manual trigger/poll/fetchconstjob=awaitclient.discoverTrigger('market research SaaS',{intent: 'competitor pricing strategies',});awaitjob.wait({timeout: 60_000});constdata=awaitjob.fetch();

Scraper Studio

Trigger and fetch results from your custom scrapers built in Scraper Studio.

// Orchestrated — trigger + poll + return resultsconstresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: {url: 'https://example.com/product/1'},});// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }// Multiple inputs (processed sequentially)constresults=awaitclient.scraperStudio.run('c_your_collector_id',{input: [{url: 'https://example.com/product/1'},{url: 'https://example.com/product/2'},],});// Manual control — trigger, then poll yourselfconstjob=awaitclient.scraperStudio.trigger('c_your_collector_id',{url: 'https://example.com/product/1',});constdata=awaitjob.waitAndFetch();// Check job status (by job ID from the dashboard)conststatus=awaitclient.scraperStudio.status('j_abc123');console.log(status.status);// 'queued' | 'running' | 'done' | 'failed'

Browser API

Build CDP WebSocket URLs for connecting Playwright, Puppeteer, or Selenium to Bright Data's cloud browsers. Credentials come from browserUsername/browserPassword options or BRIGHTDATA_BROWSERAPI_USERNAME/BRIGHTDATA_BROWSERAPI_PASSWORD env vars.

// Get a connection URLconsturl=client.browser.getConnectUrl();// Geo-target the browser with a 2-letter country codeconstusUrl=client.browser.getConnectUrl({country: 'us'});// Connect with Playwrightimport{chromium}from'playwright';constbrowser=awaitchromium.connectOverCDP(url);constpage=awaitbrowser.newPage();awaitpage.goto('https://example.com');consthtml=awaitpage.content();awaitbrowser.close();

Datasets

Access 126 pre-built datasets for querying and downloading structured data snapshots.

constds=client.datasets;// List all datasets available on your accountconstlist=awaitds.list();// Get field metadata for a datasetconstmeta=awaitds.instagramProfiles.getMetadata();console.log(meta.fields);// [{ name, type, description }, ...]// Query a dataset (triggers a snapshot)constsnapshotId=awaitds.instagramProfiles.query({url: 'https://www.instagram.com/natgeo/'},{records_limit: 10},);// Check snapshot statusconststatus=awaitds.instagramProfiles.getStatus(snapshotId);console.log(status.status);// 'running' | 'ready' | ...// Download when readyconstrows=awaitds.instagramProfiles.download(snapshotId);

Available datasets:

PlatformDatasets
LinkedInlinkedinProfiles, linkedinCompanies
AmazonamazonProducts, amazonReviews, amazonSellers, amazonBestSellers, amazonProductsSearch, amazonProductsGlobal, amazonWalmart
InstagraminstagramProfiles, instagramPosts, instagramComments, instagramReels
TikToktiktokProfiles, tiktokPosts, tiktokComments, tiktokShop
X/TwitterxTwitterPosts, xTwitterProfiles

Saving results

constdata=awaitclient.scrapeUrl('https://example.com');constfilePath=awaitclient.saveResults(data,{filename: 'results.json',format: 'json',});console.log(`Saved to: ${filePath}`);

Configuration

Runtime support

Node.js (>= 20) is the supported and tested runtime. The SDK also runs under Bun without crashing, but with a real caveat: Bun's bundled undici provides only a bare-bones Agent (no compose(), no close(), no custom dispatch), and Bun's request()/stream() ignore the dispatcher option entirely, routing through Bun's own native HTTP client instead. In practice this means requests still succeed under Bun, but none of Transport's tuning — connection pooling, keep-alive, custom timeouts, automatic retry on 429/500/502/503/504, and DNS caching — has any effect there; Bun's own defaults apply instead. The SDK detects the missing capabilities automatically (never crashes construction or close()), rather than failing.

API Token

Get your API token from Bright Data Control Panel.

Already logged in with the CLI? The SDK works with no configuration. If you've run brightdata login with the Bright Data CLI, the SDK automatically picks up those stored credentials. The token is resolved in this order:

  1. apiKey passed to new bdclient({ apiKey })
  2. BRIGHTDATA_API_TOKEN (or BRIGHTDATA_API_KEY) environment variable
  3. Credentials stored by the CLI (brightdata login)

If none are found, the client throws with instructions to log in or set a token.

Environment Variables

BRIGHTDATA_API_TOKEN=your_api_token# BRIGHTDATA_API_KEY also acceptedBRIGHTDATA_WEB_UNLOCKER_ZONE=your_web_unlocker_zone# OptionalBRIGHTDATA_SERP_ZONE=your_serp_zone# OptionalBRIGHTDATA_BROWSERAPI_USERNAME=your_browser_username# Optional, for Browser APIBRIGHTDATA_BROWSERAPI_PASSWORD=your_browser_password# Optional, for Browser APIBRIGHTDATA_VERBOSE=1# Optional, enable verbose logging

Tip: When loading these from a .env file with node --env-file=.env, note that variables already set in your shell take precedence over the file.

Client Options

constclient=newbdclient({apiKey: 'string',// API token (or use BRIGHTDATA_API_TOKEN env var)timeout: 120000,// Request timeout in ms (1000–300000)autoCreateZones: true,// Auto-create zones if they don't existwebUnlockerZone: 'string',// Custom web unlocker zone nameserpZone: 'string',// Custom SERP zone namelogLevel: 'INFO',// 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'structuredLogging: true,// Use structured JSON loggingverbose: false,// Enable verbose loggingrateLimit: 0,// Max requests per period (0 = unlimited)ratePeriod: 1000,// Rate limit period in ms});

Resource Cleanup

The client maintains HTTP connections. Always close when done:

awaitclient.close();// Or use Symbol.asyncDispose (TypeScript 5.2+)awaitusingclient=newbdclient();

Constants

ConstantDefaultDescription
DEFAULT_CONCURRENCY10Max parallel tasks
DEFAULT_TIMEOUT120000Request timeout (milliseconds)
MAX_RETRIES3Retry attempts on failure
RETRY_BACKOFF_FACTOR1.5Exponential backoff multiplier

Zone Management

constzones=awaitclient.listZones();console.log(`Found ${zones.length} zones`);

Subpath Exports

For tree-shaking or importing only what you need:

import{ScrapeRouter,LinkedinAPI}from'@brightdata/sdk/scrapers';import{SearchRouter}from'@brightdata/sdk/search';import{DatasetsClient,BaseDataset}from'@brightdata/sdk/datasets';

Error Handling

The SDK exports typed error classes that extend BRDError:

import{bdclient,ValidationError,AuthenticationError,BRDError}from'@brightdata/sdk';try{constresult=awaitclient.scrapeUrl('https://example.com');}catch(error){if(errorinstanceofValidationError){console.error('Invalid input:',error.message);}elseif(errorinstanceofAuthenticationError){console.error('Auth failed:',error.message);}elseif(errorinstanceofBRDError){console.error('SDK error:',error.message);}}

Error types:ValidationError, AuthenticationError, ZoneError, NetworkError, NetworkTimeoutError, TimeoutError, APIError, DataNotReadyError, FSError

Troubleshooting

Windows & corporate networks

ProblemFix
npm.ps1 cannot be loaded because running scripts is disabled (PowerShell)Use cmd instead of PowerShell, or run npm.cmd <command>, or run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. If overridden by Group Policy, contact your IT team.
SELF_SIGNED_CERT_IN_CHAIN during npm installYour network uses SSL inspection. Point npm to your corporate root certificate: npm config set cafile "C:\path\to\corporate-root.cer"
Certificate errors at runtimeSet the env variable NODE_EXTRA_CA_CERTS=C:\path\to\corporate-root.cer so Node trusts your corporate certificate.

AuthenticationError: invalid API key

If you get this error, check the following in order:

  1. Verify the token itself works, outside the SDK:
    curl -H "Authorization: Bearer YOUR_TOKEN" https://api.brightdata.com/zone/get_active_zones
    If this fails, generate a new API key with admin permissions in the control panel. Note the SDK needs an account-level API token — not a zone password.
  2. Check for shell overrides. Environment variables set in your shell take precedence over .env files loaded with node --env-file=.env. Run set BRIGHTDATA (Windows) or env | grep BRIGHTDATA (macOS/Linux) and clear any leftover values.
  3. Check your .env file: no quotes, no spaces around =, no trailing whitespace, and the token copied exactly (including dashes). Prefer LF line endings.
  4. Print what actually loaded:
    console.log(JSON.stringify(process.env.BRIGHTDATA_API_TOKEN));
    Hidden characters like \r will be visible in the output.

Support

For any issues, contact Bright Data support, or open an issue in this repository.

License

This project is licensed under the MIT License.

About

Bright Data's JS SDK, use it to call bright data's scrape and search tools. bypass any Bot-detection or Captcha and extract data from the web.

Topics

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages