scrapebadger 0.24.2 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/{index-jp8WyFsJ.d.cts → index-ZD3sVCjc.d.cts} +16 -0
- package/dist/{index-jp8WyFsJ.d.ts → index-ZD3sVCjc.d.ts} +16 -0
- package/dist/index.d.cts +465 -23
- package/dist/index.d.ts +465 -23
- package/dist/index.js +227 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +224 -1
- package/dist/index.mjs.map +1 -1
- package/dist/twitter/index.d.cts +1 -1
- package/dist/twitter/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -137,6 +137,39 @@ var BaseClient = class _BaseClient {
|
|
|
137
137
|
const { data } = await this.requestRaw(path, options);
|
|
138
138
|
return data;
|
|
139
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* POST and return the undecoded response body.
|
|
142
|
+
*
|
|
143
|
+
* For endpoints that answer with something other than JSON — currently
|
|
144
|
+
* `/v1/web/scrape` with `raw_content: true`, which returns the scraped body
|
|
145
|
+
* itself. The normal path funnels a non-JSON response into
|
|
146
|
+
* `{ detail: await response.text() }`, which both loses the result and, for
|
|
147
|
+
* a binary payload, corrupts it: `text()` decodes bytes as UTF-8.
|
|
148
|
+
*
|
|
149
|
+
* Returns the raw bytes plus the response headers.
|
|
150
|
+
*/
|
|
151
|
+
async postBinary(path, options = {}) {
|
|
152
|
+
const url = new URL(path, this.config.baseUrl);
|
|
153
|
+
const { body, headers = {} } = options;
|
|
154
|
+
const response = await this.fetchWithTimeout(url.toString(), {
|
|
155
|
+
method: "POST",
|
|
156
|
+
headers: {
|
|
157
|
+
"Content-Type": "application/json",
|
|
158
|
+
"X-API-Key": this.config.apiKey,
|
|
159
|
+
"User-Agent": `scrapebadger-node/${SDK_VERSION}`,
|
|
160
|
+
...headers
|
|
161
|
+
},
|
|
162
|
+
body: body ? JSON.stringify(body) : void 0
|
|
163
|
+
});
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
await this.handleResponse(response);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
bytes: new Uint8Array(await response.arrayBuffer()),
|
|
169
|
+
headers: response.headers,
|
|
170
|
+
status: response.status
|
|
171
|
+
};
|
|
172
|
+
}
|
|
140
173
|
/**
|
|
141
174
|
* Make an HTTP request and return both data and rate limit headers.
|
|
142
175
|
*/
|
|
@@ -2481,11 +2514,54 @@ var WebClient = class {
|
|
|
2481
2514
|
if (options.aiPrompt !== void 0) body.ai_prompt = options.aiPrompt;
|
|
2482
2515
|
if (options.rawContent !== void 0) body.raw_content = options.rawContent;
|
|
2483
2516
|
if (options.skipBotDetection !== void 0) body.skip_bot_detection = options.skipBotDetection;
|
|
2517
|
+
if (options.rawContent) {
|
|
2518
|
+
return this.scrapeRaw(body);
|
|
2519
|
+
}
|
|
2484
2520
|
return this.client.request("/v1/web/scrape", {
|
|
2485
2521
|
method: "POST",
|
|
2486
2522
|
body
|
|
2487
2523
|
});
|
|
2488
2524
|
}
|
|
2525
|
+
/**
|
|
2526
|
+
* Run a `rawContent` scrape, whose response is not JSON.
|
|
2527
|
+
*
|
|
2528
|
+
* The normal path funnels a non-JSON response into `{ detail: text }`, so a
|
|
2529
|
+
* raw scrape returned a result with no content — and for a binary target,
|
|
2530
|
+
* `response.text()` decoded the bytes as UTF-8 and destroyed them. Read the
|
|
2531
|
+
* body as bytes and rebuild the metadata from the `X-Scrape-*` headers the
|
|
2532
|
+
* server sends in this mode.
|
|
2533
|
+
*/
|
|
2534
|
+
async scrapeRaw(body) {
|
|
2535
|
+
const { bytes, headers, status } = await this.client.postBinary("/v1/web/scrape", {
|
|
2536
|
+
body
|
|
2537
|
+
});
|
|
2538
|
+
const int = (name) => {
|
|
2539
|
+
const parsed = Number.parseInt(headers.get(name) ?? "", 10);
|
|
2540
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
2541
|
+
};
|
|
2542
|
+
const mediaType = ((headers.get("content-type") ?? "").split(";")[0] ?? "").trim().toLowerCase();
|
|
2543
|
+
const isText = mediaType.startsWith("text/") || ["application/json", "application/xml", "image/svg+xml"].includes(mediaType);
|
|
2544
|
+
return {
|
|
2545
|
+
success: headers.get("x-scrape-success") !== "0",
|
|
2546
|
+
url: headers.get("x-scrape-url") ?? (typeof body.url === "string" ? body.url : ""),
|
|
2547
|
+
status_code: int("x-scrape-status-code") || status,
|
|
2548
|
+
content: isText ? new TextDecoder().decode(bytes) : null,
|
|
2549
|
+
content_bytes: bytes,
|
|
2550
|
+
content_base64: null,
|
|
2551
|
+
is_binary: !isText,
|
|
2552
|
+
content_type: mediaType || null,
|
|
2553
|
+
format: headers.get("x-scrape-format") ?? "html",
|
|
2554
|
+
engine_used: headers.get("x-scrape-engine") ?? "",
|
|
2555
|
+
credits_used: int("x-credits-used"),
|
|
2556
|
+
duration_ms: int("x-scrape-duration-ms"),
|
|
2557
|
+
retries_used: int("x-scrape-retries"),
|
|
2558
|
+
content_length: int("x-scrape-content-length") || bytes.length,
|
|
2559
|
+
screenshot_url: null,
|
|
2560
|
+
video_url: null,
|
|
2561
|
+
headers: {},
|
|
2562
|
+
blocking_detected: false
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2489
2565
|
/**
|
|
2490
2566
|
* Extract structured data from a web page using AI.
|
|
2491
2567
|
*
|
|
@@ -6750,6 +6826,150 @@ var LinkedInClient = class {
|
|
|
6750
6826
|
}
|
|
6751
6827
|
};
|
|
6752
6828
|
|
|
6829
|
+
// src/chatgpt/ask.ts
|
|
6830
|
+
var AskClient = class {
|
|
6831
|
+
client;
|
|
6832
|
+
constructor(client) {
|
|
6833
|
+
this.client = client;
|
|
6834
|
+
}
|
|
6835
|
+
/**
|
|
6836
|
+
* Ask ChatGPT a question and get the answer with its sources.
|
|
6837
|
+
*
|
|
6838
|
+
* Costs 20 credits. Typical latency is 20-25s ungrounded, 30-70s with web search.
|
|
6839
|
+
*
|
|
6840
|
+
* @param params - Ask parameters.
|
|
6841
|
+
* @param params.prompt - The prompt to send (max 4096 characters).
|
|
6842
|
+
* @param params.country - ISO-3166 alpha-2 egress country (default: "US").
|
|
6843
|
+
* @param params.web_search - "auto", "force", or "off" (default: "auto").
|
|
6844
|
+
* @returns The answer, its citations, and the full retrieved search set.
|
|
6845
|
+
*
|
|
6846
|
+
* @example
|
|
6847
|
+
* ```typescript
|
|
6848
|
+
* const result = await client.chatgpt.ask.ask({
|
|
6849
|
+
* prompt: "what is the best CRM for a 10-person startup?",
|
|
6850
|
+
* country: "GB",
|
|
6851
|
+
* web_search: "force",
|
|
6852
|
+
* });
|
|
6853
|
+
* console.log(result.web_search_triggered, result.model);
|
|
6854
|
+
* for (const source of result.search_results) {
|
|
6855
|
+
* console.log(`${source.cited ? "*" : " "} ${source.url}`);
|
|
6856
|
+
* }
|
|
6857
|
+
* ```
|
|
6858
|
+
*/
|
|
6859
|
+
async ask(params) {
|
|
6860
|
+
return this.client.request("/v1/chatgpt/ask", {
|
|
6861
|
+
params: {
|
|
6862
|
+
prompt: params.prompt,
|
|
6863
|
+
country: params.country,
|
|
6864
|
+
web_search: params.web_search
|
|
6865
|
+
}
|
|
6866
|
+
});
|
|
6867
|
+
}
|
|
6868
|
+
};
|
|
6869
|
+
|
|
6870
|
+
// src/chatgpt/brand.ts
|
|
6871
|
+
var BrandClient = class {
|
|
6872
|
+
client;
|
|
6873
|
+
constructor(client) {
|
|
6874
|
+
this.client = client;
|
|
6875
|
+
}
|
|
6876
|
+
/**
|
|
6877
|
+
* Analyse how a brand shows up in ChatGPT's answer to a prompt.
|
|
6878
|
+
*
|
|
6879
|
+
* Costs 25 credits.
|
|
6880
|
+
*
|
|
6881
|
+
* @param params - Brand-visibility parameters.
|
|
6882
|
+
* @param params.prompt - The prompt to send (max 4096 characters).
|
|
6883
|
+
* @param params.brand - The brand name to look for in the answer.
|
|
6884
|
+
* @param params.domain - The brand's domain, used to detect brand citations.
|
|
6885
|
+
* @param params.aliases - Other spellings that should count as mentions.
|
|
6886
|
+
* @param params.competitors - Competitors to measure share of voice against.
|
|
6887
|
+
* @param params.country - ISO-3166 alpha-2 egress country (default: "US").
|
|
6888
|
+
* @param params.web_search - "auto", "force", or "off" (default: "force").
|
|
6889
|
+
* @returns The brand analysis plus the answer and its citations.
|
|
6890
|
+
*
|
|
6891
|
+
* @example
|
|
6892
|
+
* ```typescript
|
|
6893
|
+
* const result = await client.chatgpt.brand.visibility({
|
|
6894
|
+
* prompt: "which proxy provider should I use?",
|
|
6895
|
+
* brand: "ScrapeBadger",
|
|
6896
|
+
* domain: "scrapebadger.com",
|
|
6897
|
+
* aliases: ["Scrape Badger"],
|
|
6898
|
+
* competitors: ["Bright Data", "Oxylabs"],
|
|
6899
|
+
* country: "DE",
|
|
6900
|
+
* });
|
|
6901
|
+
* console.log(`position score: ${result.position_score}`);
|
|
6902
|
+
* for (const competitor of result.competitors) {
|
|
6903
|
+
* console.log(`${competitor.name}: ${competitor.mention_count}`);
|
|
6904
|
+
* }
|
|
6905
|
+
* ```
|
|
6906
|
+
*/
|
|
6907
|
+
async visibility(params) {
|
|
6908
|
+
return this.client.request("/v1/chatgpt/brand-visibility", {
|
|
6909
|
+
params: {
|
|
6910
|
+
prompt: params.prompt,
|
|
6911
|
+
brand: params.brand,
|
|
6912
|
+
domain: params.domain,
|
|
6913
|
+
aliases: params.aliases?.length ? params.aliases.join(",") : void 0,
|
|
6914
|
+
competitors: params.competitors?.length ? params.competitors.join(",") : void 0,
|
|
6915
|
+
country: params.country,
|
|
6916
|
+
web_search: params.web_search
|
|
6917
|
+
}
|
|
6918
|
+
});
|
|
6919
|
+
}
|
|
6920
|
+
};
|
|
6921
|
+
|
|
6922
|
+
// src/chatgpt/reference.ts
|
|
6923
|
+
var ReferenceClient11 = class {
|
|
6924
|
+
client;
|
|
6925
|
+
constructor(client) {
|
|
6926
|
+
this.client = client;
|
|
6927
|
+
}
|
|
6928
|
+
/**
|
|
6929
|
+
* Get the models chatgpt.com currently offers.
|
|
6930
|
+
*
|
|
6931
|
+
* Costs 1 credit.
|
|
6932
|
+
*
|
|
6933
|
+
* @param params - Optional parameters.
|
|
6934
|
+
* @param params.country - ISO-3166 alpha-2 egress country (default: "US").
|
|
6935
|
+
* @returns The available models.
|
|
6936
|
+
*
|
|
6937
|
+
* @example
|
|
6938
|
+
* ```typescript
|
|
6939
|
+
* const result = await client.chatgpt.reference.models({ country: "GB" });
|
|
6940
|
+
* console.log(`${result.count} models`);
|
|
6941
|
+
* for (const model of result.models) {
|
|
6942
|
+
* console.log(`${model.slug}: ${model.max_tokens} tokens`);
|
|
6943
|
+
* }
|
|
6944
|
+
* ```
|
|
6945
|
+
*/
|
|
6946
|
+
async models(params = {}) {
|
|
6947
|
+
return this.client.request("/v1/chatgpt/models", {
|
|
6948
|
+
params: { country: params.country }
|
|
6949
|
+
});
|
|
6950
|
+
}
|
|
6951
|
+
};
|
|
6952
|
+
|
|
6953
|
+
// src/chatgpt/client.ts
|
|
6954
|
+
var ChatGPTClient = class {
|
|
6955
|
+
/** Client for asking ChatGPT a question */
|
|
6956
|
+
ask;
|
|
6957
|
+
/** Client for AEO/GEO brand-visibility analysis */
|
|
6958
|
+
brand;
|
|
6959
|
+
/** Client for reference data (available models) */
|
|
6960
|
+
reference;
|
|
6961
|
+
/**
|
|
6962
|
+
* Create a new ChatGPT client.
|
|
6963
|
+
*
|
|
6964
|
+
* @param client - The base HTTP client for making requests.
|
|
6965
|
+
*/
|
|
6966
|
+
constructor(client) {
|
|
6967
|
+
this.ask = new AskClient(client);
|
|
6968
|
+
this.brand = new BrandClient(client);
|
|
6969
|
+
this.reference = new ReferenceClient11(client);
|
|
6970
|
+
}
|
|
6971
|
+
};
|
|
6972
|
+
|
|
6753
6973
|
// src/client.ts
|
|
6754
6974
|
var ScrapeBadger = class {
|
|
6755
6975
|
baseClient;
|
|
@@ -6789,6 +7009,8 @@ var ScrapeBadger = class {
|
|
|
6789
7009
|
depop;
|
|
6790
7010
|
/** LinkedIn scraper API client — 11 no-auth endpoints (jobs, company, school, profile, post, article, learning, geo) */
|
|
6791
7011
|
linkedin;
|
|
7012
|
+
/** ChatGPT scraper API client — ask, brand visibility, models (the real chatgpt.com, anonymous) */
|
|
7013
|
+
chatgpt;
|
|
6792
7014
|
/**
|
|
6793
7015
|
* Create a new ScrapeBadger client.
|
|
6794
7016
|
*
|
|
@@ -6841,6 +7063,7 @@ var ScrapeBadger = class {
|
|
|
6841
7063
|
this.loopnet = new LoopNetClient(this.baseClient);
|
|
6842
7064
|
this.depop = new DepopClient(this.baseClient);
|
|
6843
7065
|
this.linkedin = new LinkedInClient(this.baseClient);
|
|
7066
|
+
this.chatgpt = new ChatGPTClient(this.baseClient);
|
|
6844
7067
|
}
|
|
6845
7068
|
};
|
|
6846
7069
|
|
|
@@ -6852,6 +7075,10 @@ exports.AmazonReferenceClient = ReferenceClient2;
|
|
|
6852
7075
|
exports.AmazonSearchClient = SearchClient4;
|
|
6853
7076
|
exports.AmazonSellersClient = SellersClient;
|
|
6854
7077
|
exports.AuthenticationError = AuthenticationError;
|
|
7078
|
+
exports.ChatGPTAskClient = AskClient;
|
|
7079
|
+
exports.ChatGPTBrandClient = BrandClient;
|
|
7080
|
+
exports.ChatGPTClient = ChatGPTClient;
|
|
7081
|
+
exports.ChatGPTReferenceClient = ReferenceClient11;
|
|
6855
7082
|
exports.CommunitiesClient = CommunitiesClient;
|
|
6856
7083
|
exports.ConflictError = ConflictError;
|
|
6857
7084
|
exports.DepopClient = DepopClient;
|