JavaScript SDK Specification
Examples on this page match desearch-js@1.5.1. extract() is the extract call. webCrawl() remains a deprecated alias on this version. New code should call extract().
First AI Search call: Search API. Page fetch: Extract API. Keys: Auth and API keys.
Install
Requires Node.js 20.18.1 or later. Node 18 is not supported. npm still installs the package on Node 18 with an EBADENGINE warning, but that setup is not tested.
Pin the version used in these examples:
Use 1.5.1 or later. On 1.5.0, importing the package could crash with TypeError: webidl.util.markAsUncloneable is not a function when the package manager installed undici 8 at the top level of the project. 1.5.1 limits its undici dependency to versions 6 and 7 and loads correctly even when undici 8 is present.
Construct the client
Desearch is both the default export and a named export. Pass the raw API key. Do not expose production keys in browser bundles.
ES modules:
CommonJS:
Do not pass streaming into aiSearch. The method always sends a non-stream request. For "streaming": true, call REST. See Streaming AI Search.
Extract
Billing metadata
Read request cost from response headers. JSON object bodies may also include cost_usd, usage_count, service, and currency.
| Header | Meaning |
|---|---|
X-Desearch-Cost-Usd | Request cost in USD |
X-Desearch-Usage-Count | Billable usage units |
X-Desearch-Service | Pricing service key |
X-Desearch-Currency | Currency code |
Arrays, text responses, and streaming responses keep their body shape. Use headers for those. This page does not list dollar rates.
Errors
- Missing or invalid key:
401. - Validation failure:
4xxwith the API message. 429or5xx: retry with backoff.
Do not invent error JSON schemas beyond the API Reference.
Parity with Python
| Capability | Python 1.2.1 | JavaScript 1.5.1 |
|---|---|---|
| AI Search | ai_search(...) | aiSearch({...}) |
| Extract page content | REST /web/extract or web_crawl | extract({...}) |
| Streaming helpers | Not on this package. Use REST (streaming guide) | Same |
| Billing fields on a JSON object | Read body and headers | Same |
| Billing on a stream | Headers only | Headers only |
| People Search (Python 1.4.0, JavaScript 1.6.0) | x_profile_search(...), youtube_creator_search(...), linkedin_profile_search(...), tiktok_creator_search(...) | xProfileSearch({...}), youtubeCreatorSearch({...}), linkedinProfileSearch({...}), tiktokCreatorSearch({...}) |
| Wait for a People Search task | wait_for_people_task(task_id) | waitForPeopleTask(task) |
| Read every People Search result | iter_people_results(task_id) | iterPeopleResultPages({ task_id }) |
People Search metadata labels (Python 1.5.0, JavaScript 1.7.0) | metadata={...} on the search methods and list_people_tasks | metadata: {...} in the search request and in listPeopleTasks |
Python extract() is not on PyPI desearch-py 1.2.1. See the Python SDK.
Other methods already on this package
Web search:
X search:
People Search (1.6.0 and later)
People Search methods ship in desearch-js 1.6.0. The examples above match 1.5.1.
A search runs in the background. Start it, wait for it, then read or export the people it found:
| Method | Route |
|---|---|
xProfileSearch, youtubeCreatorSearch, linkedinProfileSearch, tiktokCreatorSearch | POST /desearch/people/search/{x,youtube,linkedin,tiktok} (billed) |
listPeopleTasks | GET /desearch/people/tasks |
getPeopleTask | GET /desearch/people/tasks/{task_id} |
getPeopleResults | GET /desearch/people/tasks/{task_id}/results |
pausePeopleTask, resumePeopleTask, cancelPeopleTask | POST /desearch/people/tasks/{task_id}/pause, /resume, /cancel |
exportPeopleResults | GET /desearch/people/tasks/{task_id}/export |
listPeopleProfiles | GET /desearch/people/profiles |
exportPeopleProfiles | GET /desearch/people/profiles/export |
waitForPeopleTask | Polls getPeopleTask until the task ends |
iterPeopleResultPages | Follows next_cursor on getPeopleResults |
Each search request takes query, count, min_score, exclude, and that platform's filters, plus metadata from 1.7.0 (below). idempotencyKey in the second argument is sent as the Idempotency-Key header. Pause, resume, and cancel throw PeopleTaskConflictError on HTTP 409. waitForPeopleTask throws when timeoutMs passes; the search keeps running. Flow, filters, and billing: People Search.
Label searches with metadata (1.7.0 and later)
desearch-js 1.7.0 adds metadata to the four search methods and a metadata option to listPeopleTasks. Use it to tag each search with your own labels, such as the campaign, workspace, or customer it belongs to, and to list those searches later. The search itself never uses the labels.
task.metadatais{}for a search without labels.- A search takes up to 10 keys. Keys are 1 to 40 characters of
a-z,0-9,_,., or-, and values are strings of up to 200 characters. The SDK does not check them; the API answers422otherwise. listPeopleTaskssends each pair as ametadata.<key>=<value>query parameter, and a task must match all of them exactly. Pass up to 3 pairs (the API answers400otherwise), and pass the samemetadatawith eachcursorwhen you page.- This
metadatais the task's labels. It is not the costmetadatathat{ includeMetadata: true }returns.