
AI with JavaScript and Node.js: A Beginner's Guide
Yes, you can build real AI features with JavaScript, and in 2026 it is one of the easiest ways to do it. Most AI features in web apps are a call to a large language model (LLM) API, which in JS is a single fetch request from your server, or a few lines with the AI SDK. For private or offline features, libraries like Transformers.js and WebLLM run models directly in the browser. Node.js AI works the same way on the server, plus ONNX Runtime and TensorFlow.js for running your own models. This guide walks through each option with runnable code, and explains what it costs.
AI in JS: three ways to add artificial intelligence to a JavaScript app
| Approach | What runs where | Good for | Cost |
|---|---|---|---|
Call an LLM API with fetch |
Your server calls a hosted model (Claude, GPT, Gemini...) | Chat, summarizing, writing, extraction, coding help | Pay per token |
| Use the AI SDK | Same, through one TypeScript API for many providers | Streaming chat UIs, switching providers, tool calling, agents | Pay per token (the SDK itself is free and open source) |
| Run a model in the browser | The user's device (WASM or WebGPU) | Sentiment, embeddings, speech-to-text, small chat models, privacy | Free per request; large one-time download for the user |
The older approach, training your own neural networks with TensorFlow.js, still works, but beginners rarely need it now: pre-trained models through an API or Transformers.js cover most features.
Before you start: install Node.js 18 or newer (it has fetch built in), and keep API keys on the server. Never put a secret API key in browser code; anyone can read it in DevTools and spend your money.
1. Call an LLM API with fetch
Every major provider exposes a plain HTTPS API. Here is the Claude Messages API, called with nothing but fetch. Save it as ask.mjs:
// ask.mjs - run with: ANTHROPIC_API_KEY=sk-... node ask.mjs
const res = 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-haiku-5-5",
max_tokens: 500,
messages: [
{ role: "user", content: "Explain JavaScript closures in two sentences." },
],
}),
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
const data = await res.json();
console.log(data.content.find((block) => block.type === "text").text);
console.log(data.usage); // { input_tokens: ..., output_tokens: ... }
What is going on:
- You send a list of
messages(the conversation so far) and amodelID. max_tokenscaps the length of the answer, which also caps the cost.- The reply comes back as JSON; the text is in
content, andusagetells you how many tokens you paid for.
OpenAI, Google Gemini and others work the same way with different URLs and field names. For a chat, keep the messages array and append each user message and model reply to it before the next request.
2. Use the AI SDK (one API for every provider)
Writing raw fetch code for each provider gets old fast, especially for streaming. The AI SDK (the ai package on npm, currently version 7) gives you one TypeScript API across providers.
npm install ai
Generate text:
import { generateText } from "ai";
const { text } = await generateText({
model: "anthropic/claude-sonnet-5.5",
prompt: "Write a one-line commit message for: fixed null check in login form",
});
console.log(text);
A plain string like "anthropic/claude-sonnet-5.5" routes through Vercel's AI Gateway and reads the AI_GATEWAY_API_KEY environment variable, per the AI SDK Node.js guide. If you'd rather use your own provider key directly, install a provider package (for example @ai-sdk/anthropic or @ai-sdk/openai) and pass its model object instead of the string. Changing providers is then a one-line change.
Streaming responses
LLMs produce text token by token. Streaming shows the answer as it is written instead of making the user wait several seconds for the whole reply. With the AI SDK, streamText returns an async iterable:
import { streamText } from "ai";
const result = streamText({
model: "anthropic/claude-sonnet-5.5",
prompt: "Give me three name ideas for a habit-tracking app.",
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}
In a web app, stream from a server route to the browser. A Next.js App Router route handler (app/api/ask/route.ts):
import { streamText } from "ai";
export async function POST(req: Request) {
const { prompt } = await req.json();
const result = streamText({ model: "anthropic/claude-sonnet-5.5", prompt });
return result.toTextStreamResponse();
}
And plain browser JavaScript that reads the stream as it arrives:
const res = await fetch("/api/ask", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ prompt: "Summarize the plot of Hamlet in 3 lines." }),
});
const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
const output = document.querySelector("#output");
while (true) {
const { value, done } = await reader.read();
if (done) break;
output.textContent += value;
}
For full chat interfaces in React, Vue or Svelte, the AI SDK's UI hooks (such as useChat) handle message state and streaming for you. If you build with AI coding tools, DevHunt's vibe coding guide covers that workflow.
3. AI in Node.js: SDKs, local models and machine learning
Node.js is where most JavaScript AI code actually runs, because that's where your API keys and data live. Everything in sections 1 and 2 is Node.js code already. The main Node.js AI options, with npm versions as of October 2026:
| Package | What it does | Runs |
|---|---|---|
ai (AI SDK, 7.x) |
One API for many hosted LLMs, streaming, tool calling, agents | Calls hosted models |
@anthropic-ai/sdk, openai |
Official provider SDKs with types, retries and streaming | Calls hosted models |
@huggingface/transformers (4.x) |
Pre-trained models for embeddings, classification, speech, vision | Locally, on CPU (or GPU where supported) |
onnxruntime-node (1.30) |
Microsoft's runtime for any model exported to ONNX format | Locally; prebuilt for Windows, macOS, Linux (CPU), CUDA on Linux x64, DirectML on Windows |
@tensorflow/tfjs-node (4.22) |
Train and run TensorFlow.js models with native TensorFlow bindings | Locally; last release October 2024 |
Local models in Node.js with Transformers.js
Transformers.js uses the same pipeline API in Node.js as in the browser (it runs on ONNX Runtime under the hood). Embeddings for semantic search, for example:
// embed.mjs - run with: node embed.mjs
import { pipeline } from "@huggingface/transformers";
const embed = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
const output = await embed(["How do I reset my password?"], {
pooling: "mean",
normalize: true,
});
console.log(output.dims); // [1, 384]: one 384-number vector per sentence
The model downloads on first run and is cached on disk. Store the vectors in a database with vector search (Postgres with pgvector, for example) and compare them with cosine similarity to find related text, all without paying per request.
ONNX Runtime and TensorFlow.js: Node.js machine learning
If a data scientist trained a model in Python (PyTorch or scikit-learn), export it to ONNX and run it in Node.js with ONNX Runtime:
import * as ort from "onnxruntime-node";
const session = await ort.InferenceSession.create("./model.onnx");
const input = new ort.Tensor("float32", Float32Array.from([5.1, 3.5, 1.4, 0.2]), [1, 4]);
const results = await session.run({ [session.inputNames[0]]: input });
console.log(results[session.outputNames[0]].data);
Input names, shapes and types depend on the model, so check them in session.inputNames or a viewer like Netron.
To train a small model in JavaScript itself, TensorFlow.js still works, and @tensorflow/tfjs-node binds it to the native TensorFlow library for speed. But its last npm release was 4.22.0 in October 2024 and it ships native binaries, so test that it installs on your Node.js version before depending on it. For new work, training in Python and serving through ONNX Runtime in Node.js is the more future-proof route.
Is Node.js good for AI?
For building AI features, yes: an LLM call is network I/O, which is what Node.js's event loop handles well, and streaming responses to thousands of users fits it naturally. For training large models or heavy numeric work, no: Python's ecosystem (PyTorch, NumPy, CUDA tooling) is far ahead. Many teams use both, with Python for training and Node.js for the product.
4. Run AI models in the browser
Running a model on the user's device means no per-request cost, no server, and data that never leaves the machine. The trade-off: the user downloads the model first, and small on-device models are less capable than hosted ones.
Transformers.js: ready-made models in a few lines
Transformers.js (@huggingface/transformers, version 4) runs thousands of models from Hugging Face in the browser or Node.js. Tasks include sentiment analysis, text classification, translation, summarization, embeddings, speech recognition and image classification.
npm install @huggingface/transformers
import { pipeline } from "@huggingface/transformers";
// Downloads a small model on first use, then caches it in the browser
const classify = await pipeline(
"sentiment-analysis",
"Xenova/distilbert-base-uncased-finetuned-sst-2-english"
);
const result = await classify("I love how fast this app is!");
console.log(result); // [{ label: 'POSITIVE', score: 0.99... }]
By default it runs on the CPU with WebAssembly. Pass { device: "webgpu" } to use the GPU where supported, and { dtype: "q4" } or "q8" for smaller quantized model files.
WebLLM: a chat model inside the browser
WebLLM (@mlc-ai/web-llm) runs open LLMs such as Llama in the browser using WebGPU, with an OpenAI-style API:
import { CreateMLCEngine } from "@mlc-ai/web-llm";
const engine = await CreateMLCEngine("Llama-3.1-8B-Instruct-q4f32_1-MLC", {
initProgressCallback: (p) => console.log(p.text), // download progress
});
const chunks = await engine.chat.completions.create({
messages: [{ role: "user", content: "Write a haiku about JavaScript." }],
stream: true,
});
let reply = "";
for await (const chunk of chunks) {
reply += chunk.choices[0]?.delta?.content || "";
}
console.log(reply);
Two cautions. It needs a WebGPU-capable browser (recent Chrome works best), and an 8B model is a multi-gigabyte download, so offer it as an opt-in or pick a smaller model from prebuiltAppConfig.model_list. Run it in a Web Worker so the page stays responsive.
What AI in JavaScript costs
Hosted LLMs charge per million tokens (MTok), separately for input and output. A token is roughly three quarters of an English word. Current Claude list prices from Anthropic's models overview:
| Model | Input per MTok | Output per MTok |
|---|---|---|
| Claude Haiku 5.5 | from $0.10 | from $0.50 |
| Claude Sonnet 5.5 | $2 | $10 |
| Claude Opus 5.5 | $4 | $20 |
Example: 1,000 chat replies, each with 500 input and 500 output tokens, on Sonnet 5.5: 0.5 MTok x $2 + 0.5 MTok x $10 = $6. On a small, cheap model the same traffic costs cents.
Ways to keep the bill down:
- Start with the cheapest model that does the job, and upgrade only where quality falls short.
- Set
max_tokens, and trim old messages from long chats (you pay for the whole history on every request). - Cache answers to repeated questions, and rate-limit per user.
- Move simple tasks (sentiment, tagging, embeddings) to Transformers.js in the browser, where they cost you nothing.
To compare prices across Claude, GPT, Gemini, Llama and others, use DevHunt's AI model pricing table.
FAQ
Can JavaScript be used for AI?
Yes. JavaScript can call any hosted LLM API, power streaming chat interfaces with the AI SDK, and run models in the browser or Node.js with Transformers.js, WebLLM or TensorFlow.js. Training large models from scratch is still mostly done in Python, but building AI features into apps is very practical in JS.
Is Python or JavaScript better for AI?
Python is better for training models, research and data science, because PyTorch and most ML tooling are Python-first. JavaScript is better for putting AI into web apps: the API calls, streaming UI and browser-side inference all happen in JS. Many teams train or fine-tune in Python and ship the feature in JavaScript.
Do I need to know machine learning to add AI to a JavaScript app?
No. Calling an LLM API requires the same skills as calling any other REST API: fetch, JSON and async/await. Knowing how prompts, tokens and context windows work helps more than math does.
Can I call the OpenAI or Claude API directly from the browser?
You shouldn't with a secret key, because anyone can copy it from the page. Call the API from a server route (Next.js route handler, Express, serverless function) and have the browser call your route, as in the streaming example above.
Can Node.js be used for machine learning?
Yes, for running models: Transformers.js and ONNX Runtime run pre-trained or Python-trained models in Node.js, and TensorFlow.js can train small models. For training large models, Python remains the better tool. The AI SDK and provider SDKs, which call hosted models, are free and open source; you pay only for model usage.