Claude API SDK for JavaScript Developers: A Guide
If you're building with Claude in a JavaScript or Node.js project, you have three practical ways to connect: Anthropic's official SDK, raw HTTPS calls to the Messages API, or a gateway like SubToAPI that wraps your existing Claude access into a standard REST API with its own key. This article walks through all three, with working code, so you can pick the right one for your stack.
The short answer: for most teams, the official @anthropic-ai/sdk package is the right starting point for prototyping, but once you're shipping a product with multiple users, usage limits, or a need for team-wide API keys, a gateway layer becomes necessary — either one you build yourself or one you adopt off the shelf.
Option 1: The official Anthropic SDK
Anthropic publishes an official JavaScript/TypeScript SDK that wraps the Messages API with typed request/response objects, retry handling, and streaming helpers.
npm install @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const message = await anthropic.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Explain event loops in one paragraph." }],
});
console.log(message.content[0].text);
This works well in Node.js and in server-side JavaScript runtimes (Deno, Bun, edge functions). It's not designed to be called directly from browser code — you'd expose your Anthropic key to every visitor, which is a security problem regardless of which SDK you use.
Option 2: Raw fetch against the Messages API
If you don't want a dependency, or you're in an environment where installing packages is awkward (serverless functions with cold-start constraints, for example), calling the REST API directly with fetch works fine:
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Summarize this ticket." }],
}),
});
const data = await response.json();
console.log(data.content[0].text);
This is essentially what the SDK does under the hood, minus the retry logic and typed interfaces. It's a reasonable choice for small scripts or when you want full control over request shaping.
Option 3: A gateway API with per-app keys
Both options above assume a single Anthropic account key, used server-side, for one application. That breaks down fast once you have multiple products, multiple developers, or need to track usage per client. This is the gap SubToAPI fills: it takes your existing Claude access and exposes it as a standard HTTPS API with its own application keys (sub_live_...), so you don't have to build key management, usage tracking, and seat permissions yourself.
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"content-type": "application/json",
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Draft a release note for v2.3." }],
}),
});
const data = await response.json();
console.log(data.content[0].text);
The request shape is close to the Messages API, so switching an existing JavaScript integration over is mostly a matter of changing the base URL and auth header. See the quickstart and Messages docs for the full reference.
Streaming responses in JavaScript
Long completions feel faster when streamed token-by-token instead of waiting for the full response. The official SDK supports this with an async iterator:
const stream = await anthropic.messages.stream({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Write a short changelog entry." }],
});
for await (const event of stream) {
if (event.type === "content_block_delta") {
process.stdout.write(event.delta.text);
}
}
If you're going through SubToAPI, streaming works the same way over server-sent events — see /docs/streaming for the event format and a Node.js example using EventSource or raw chunked reads.
Tool use from JavaScript
Tool use (function calling) lets Claude request a structured function call instead of returning plain text, which your JavaScript code then executes and feeds back. A minimal example with the official SDK:
const tools = [
{
name: "get_weather",
description: "Get current weather for a city",
input_schema: {
type: "object",
properties: { city: { type: "string" } },
required: ["city"],
},
},
];
const message = await anthropic.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
tools,
messages: [{ role: "user", content: "What's the weather in Lisbon?" }],
});
const toolCall = message.content.find((block) => block.type === "tool_use");
console.log(toolCall?.input);
The same tool definitions and flow carry over to SubToAPI's /v1/messages endpoint — details are in /docs/tools.
Choosing between the options
- Prototyping or a single internal script: use the official SDK directly.
- No dependency allowed, or edge runtime: raw
fetchcalls work fine. - Shipping a product to external users, or giving a team access without sharing one root key: a gateway with scoped keys and usage metadata saves real engineering time. SubToAPI's pricing starts at €9/month for solo developers and includes a free trial at signup, with Team and Scale tiers for per-seat access.
None of these approaches are mutually exclusive — many teams prototype with the official SDK and move request traffic through a gateway once they need multi-key access control without rewriting their integration logic.
questions
Is there an official Claude SDK for JavaScript? Yes, Anthropic maintains @anthropic-ai/sdk for Node.js and TypeScript projects, with typed requests, retries, and streaming support built in.
Can I call the Claude API directly from browser JavaScript? Not safely — it requires sending your API key to the client. Route requests through your own backend or a gateway service instead.
Do I need an SDK, or can I just use fetch? Fetch works fine for simple use cases. An SDK (or a gateway like SubToAPI) adds value once you need retries, streaming helpers, or per-application key management.