Skip to content

Commit 868a703

Browse files
authored
Merge pull request #20 from brightdata/dev
Dev
2 parents 86be352 + 31bc9be commit 868a703

164 files changed

Lines changed: 5687 additions & 361 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ await client.close();
4545
- **Web Scraping** — Scrape any website using anti-bot detection bypass and proxy support
4646
- **Search Engine Results** — Google, Bing, and Yandex search with batch support
4747
- **Platform Scrapers** — Structured data collection from LinkedIn, Amazon, Instagram, TikTok, YouTube, Reddit, and more
48-
- **Datasets** — Access 19 pre-built datasets (Amazon, LinkedIn, Instagram, TikTok, X/Twitter) with query/download support
48+
- **Discover API** — AI-powered web search with intent-based relevance ranking
49+
- **Scraper Studio** — Trigger and fetch results from custom scrapers built in Bright Data's Scraper Studio
50+
- **Datasets** — Access 126 pre-built datasets across dozens of platforms with query/download support
4951
- **Parallel Processing** — Concurrent processing for multiple URLs or queries
5052
- **Robust Error Handling** — Typed error classes with retry logic
5153
- **Zone Management** — Automatic zone creation and management
@@ -168,11 +170,77 @@ console.log(result.status); // 'ready'
168170
console.log(result.rowCount);
169171
```
170172

171-
**Available platforms:** `linkedin`, `amazon`, `instagram`, `tiktok`, `youtube`, `reddit`, `facebook`, `chatGPT`, `digikey`, `perplexity`
173+
**Available platforms:** `linkedin`, `amazon`, `instagram`, `tiktok`, `youtube`, `reddit`, `facebook`, `pinterest`, `chatGPT`, `digikey`, `perplexity`
174+
175+
### Discover API
176+
177+
AI-powered web search with relevance ranking based on intent.
178+
179+
```javascript
180+
// Basic search
181+
const result = await client.discover('artificial intelligence trends 2026');
182+
console.log(result.data); // [{ link, title, description, relevance_score }, ...]
183+
184+
// With intent for semantic ranking
185+
const result = await client.discover('Tesla battery technology', {
186+
intent: 'recent breakthroughs in EV battery chemistry',
187+
});
188+
189+
// With filtering and localization
190+
const result = await client.discover('sustainable fashion brands', {
191+
intent: 'eco-friendly clothing companies',
192+
filterKeywords: ['sustainability', 'eco-friendly', 'organic'],
193+
country: 'us',
194+
numResults: 10,
195+
});
196+
197+
// Include full page content
198+
const result = await client.discover('python asyncio tutorial', {
199+
includeContent: true,
200+
numResults: 3,
201+
});
202+
203+
// Manual trigger/poll/fetch
204+
const job = await client.discoverTrigger('market research SaaS', {
205+
intent: 'competitor pricing strategies',
206+
});
207+
await job.wait({ timeout: 60_000 });
208+
const data = await job.fetch();
209+
```
210+
211+
### Scraper Studio
212+
213+
Trigger and fetch results from your custom scrapers built in [Scraper Studio](https://brightdata.com/cp/data_collector).
214+
215+
```javascript
216+
// Orchestrated — trigger + poll + return results
217+
const results = await client.scraperStudio.run('c_your_collector_id', {
218+
input: { url: 'https://example.com/product/1' },
219+
});
220+
// results: RunResult[] — one per input with { input, data, error, responseId, elapsedMs }
221+
222+
// Multiple inputs (processed sequentially)
223+
const results = await client.scraperStudio.run('c_your_collector_id', {
224+
input: [
225+
{ url: 'https://example.com/product/1' },
226+
{ url: 'https://example.com/product/2' },
227+
],
228+
});
229+
230+
// Manual control — trigger, then poll yourself
231+
const job = await client.scraperStudio.trigger('c_your_collector_id', {
232+
url: 'https://example.com/product/1',
233+
});
234+
const data = await job.waitAndFetch();
235+
236+
// Check job status (by job ID from the dashboard)
237+
const status = await client.scraperStudio.status('j_abc123');
238+
console.log(status.status); // 'queued' | 'running' | 'done' | 'failed'
239+
```
172240

173241
### Datasets
174242

175-
Access pre-built datasets for querying and downloading structured data snapshots.
243+
Access 126 pre-built datasets for querying and downloading structured data snapshots.
176244

177245
```javascript
178246
const ds = client.datasets;

src/api/datasets/base.ts

Lines changed: 32 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { Transport, assertResponse } from '../../core/transport';
22
import { API_ENDPOINT } from '../../utils/constants';
33
import { parseJSON } from '../../utils/misc';
44
import { getLogger } from '../../utils/logger';
5-
import { wrapAPIError } from '../../utils/error-utils';
65
import { pollUntilReady } from '../../utils/polling';
76
import type {
87
DatasetMetadata,
@@ -34,41 +33,33 @@ export abstract class BaseDataset {
3433
'{dataset_id}',
3534
this.datasetId,
3635
);
37-
try {
38-
const response = await this.transport.request(url);
39-
const text = await assertResponse(response);
40-
return parseJSON<DatasetMetadata>(text);
41-
} catch (e: unknown) {
42-
wrapAPIError(e, `datasets.${this.name}.getMetadata`);
43-
}
36+
const response = await this.transport.request(url);
37+
const text = await assertResponse(response);
38+
return parseJSON<DatasetMetadata>(text);
4439
}
4540

4641
async query(
4742
filter: Record<string, unknown>,
4843
opts?: DatasetQueryOptions,
4944
): Promise<string> {
5045
this.logger.debug('query', { filter });
51-
try {
52-
const body: Record<string, unknown> = {
53-
dataset_id: this.datasetId,
54-
filter,
55-
};
56-
if (opts?.records_limit) {
57-
body.records_limit = opts.records_limit;
58-
}
59-
const response = await this.transport.request(
60-
API_ENDPOINT.DATASET_FILTER,
61-
{
62-
method: 'POST',
63-
body: JSON.stringify(body),
64-
},
65-
);
66-
const text = await assertResponse(response);
67-
const result = parseJSON<{ snapshot_id: string }>(text);
68-
return result.snapshot_id;
69-
} catch (e: unknown) {
70-
wrapAPIError(e, `datasets.${this.name}.query`);
46+
const body: Record<string, unknown> = {
47+
dataset_id: this.datasetId,
48+
filter,
49+
};
50+
if (opts?.records_limit) {
51+
body.records_limit = opts.records_limit;
7152
}
53+
const response = await this.transport.request(
54+
API_ENDPOINT.DATASET_FILTER,
55+
{
56+
method: 'POST',
57+
body: JSON.stringify(body),
58+
},
59+
);
60+
const text = await assertResponse(response);
61+
const result = parseJSON<{ snapshot_id: string }>(text);
62+
return result.snapshot_id;
7263
}
7364

7465
async sample(opts?: DatasetQueryOptions): Promise<string> {
@@ -82,33 +73,25 @@ export abstract class BaseDataset {
8273
'{snapshot_id}',
8374
snapshotId,
8475
);
85-
try {
86-
const response = await this.transport.request(url);
87-
const text = await assertResponse(response);
88-
return parseJSON<DatasetSnapshotStatus>(text);
89-
} catch (e: unknown) {
90-
wrapAPIError(e, `datasets.${this.name}.getStatus`);
91-
}
76+
const response = await this.transport.request(url);
77+
const text = await assertResponse(response);
78+
return parseJSON<DatasetSnapshotStatus>(text);
9279
}
9380

9481
async download(
9582
snapshotId: string,
9683
opts?: DatasetDownloadOptions,
9784
): Promise<unknown[]> {
9885
this.logger.debug('download', { snapshotId });
99-
try {
100-
await pollUntilReady(snapshotId, (id) => this.getStatus(id));
101-
const url = API_ENDPOINT.DATASET_SNAPSHOT_DOWNLOAD.replace(
102-
'{snapshot_id}',
103-
snapshotId,
104-
);
105-
const query: Record<string, unknown> = {};
106-
if (opts?.format) query.format = opts.format;
107-
const response = await this.transport.request(url, { query });
108-
const text = await assertResponse(response);
109-
return parseJSON<unknown[]>(text);
110-
} catch (e: unknown) {
111-
wrapAPIError(e, `datasets.${this.name}.download`);
112-
}
86+
await pollUntilReady(snapshotId, (id) => this.getStatus(id));
87+
const url = API_ENDPOINT.DATASET_SNAPSHOT_DOWNLOAD.replace(
88+
'{snapshot_id}',
89+
snapshotId,
90+
);
91+
const query: Record<string, unknown> = {};
92+
if (opts?.format) query.format = opts.format;
93+
const response = await this.transport.request(url, { query });
94+
const text = await assertResponse(response);
95+
return parseJSON<unknown[]>(text);
11396
}
11497
}

0 commit comments

Comments
 (0)