Node.js SDK
Typed TypeScript client for the ScrapingIsNotACrime API, with ESM and CommonJS builds and zero runtime dependencies.
01Install
npm install @scrapingisnotacrime/sdk
02Quick start
import { ScrapingIsNotACrime } from "@scrapingisnotacrime/sdk";
const client = new ScrapingIsNotACrime({ apiKey: process.env.SCRAPINGISNOTACRIME_API_KEY });
const profile = await client.instagram.profile("nasa");
console.log(profile.username, profile.followers);const { ScrapingIsNotACrime } = require("@scrapingisnotacrime/sdk");Get a key at your dashboard. Keys start with sinac_, and new accounts get 100 free credits.
If you omit apiKey, the client reads SCRAPINGISNOTACRIME_API_KEY from the environment.
03Configuration
new ScrapingIsNotACrime({
apiKey: "sinac_...",
baseUrl: "https://api.scrapingisnotacrime.com/v1",
timeoutMs: 30_000,
maxRetries: 2,
fetch: customFetch,
});| Option | Default | Description |
|---|---|---|
apiKey | SCRAPINGISNOTACRIME_API_KEY | Your API key. The constructor throws if none is set. Defaults to the SCRAPINGISNOTACRIME_API_KEY environment variable. |
baseUrl | https://api.scrapingisnotacrime.com/v1 | API base URL. |
timeoutMs | 30000 | Per-attempt timeout, in milliseconds. |
maxRetries | 2 | Extra attempts for 429, 502 and network errors. 0 disables retries. |
fetch | fetch | Custom fetch implementation, for tests or proxies. Defaults to the global fetch. |
A custom fetch receives an init.signal that the SDK aborts when timeoutMs elapses. Honor it so the underlying request stops too.
04Methods
Methods are grouped by platform under client.<platform> and return the response's data, typed. Paginated methods return a Page you can iterate with for await.
05Pagination
A Page exposes items, hasMore, nextCursor or nextPage, and data with the full response. Iterating it fetches further pages lazily.
Each page fetched is one billed request, so bound your loops. Breaking out early stops fetching.
const page = await client.github.followers("torvalds", { limit: 100 });
for await (const user of page) {
console.log(user.username);
}06Errors
Every failure throws a subclass of ScrapingIsNotACrimeError with status, message and requestId.
| Type | Status | Retried |
|---|---|---|
BadRequestError | 400 | no |
AuthenticationError | 401 | no |
QuotaExceededError | 402 | no |
NotFoundError | 404 | no |
RateLimitError | 429 | yes |
UpstreamError | 502 | yes |
ConnectionError | network failure or timeout | yes |
APIError | any other non-2xx response | no |
import { NotFoundError, QuotaExceededError, RateLimitError, ScrapingIsNotACrime } from "@scrapingisnotacrime/sdk";
const client = new ScrapingIsNotACrime({ maxRetries: 3 });
try {
await client.tiktok.profile("this-user-does-not-exist-123");
} catch (error) {
if (error instanceof NotFoundError) console.log("No such profile.");
else if (error instanceof QuotaExceededError) console.log("Out of credits:", error.message);
else if (error instanceof RateLimitError) console.log("TikTok is rate limiting; try again later.");
else throw error;
}07Retries
Rate limits (429), upstream failures (502) and network failures or timeouts are retried automatically, up to 2 extra attempts by default. These failures don't consume credits. The wait honors the Retry-After header; otherwise it is exponential backoff with jitter, starting at 500 ms and capped at 10 seconds.
Set maxRetries: 0 to disable retries.
08Do not use in the browser
Calling the SDK from a browser exposes your API key to anyone who opens the network tab. Call it from your server and proxy client requests through your backend.
09ESM and CommonJS
The package ships both builds. If one application loads both, there are two copies of every error class and instanceof fails across them. Stick to one module system, or check error.name or error.status.