Streaming makes your AI app feel instant — the response appears word by word instead of all at once after a delay. Day 2 implements streaming with the Claude API.
Without streaming, the user stares at a blank screen for 3-10 seconds waiting for a complete response. With streaming, they see text appear immediately. This is how every major AI product works, and users expect it.
import Anthropic from '@anthropic-ai/sdk';
import * as dotenv from 'dotenv';
dotenv.config();
const client = new Anthropic();
async function streamChat(userMessage) {
console.log('Assistant: ');
const stream = await client.messages.stream({
model: 'claude-opus-4-5',
max_tokens: 1024,
messages: [{ role: 'user', content: userMessage }]
});
// Print each text chunk as it arrives
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta' &&
chunk.delta.type === 'text_delta') {
process.stdout.write(chunk.delta.text);
}
}
// Get final message after streaming completes
const message = await stream.finalMessage();
console.log('
[Tokens used:', message.usage.input_tokens, '+', message.usage.output_tokens, ']');
return message.content[0].text;
}
await streamChat('Write a short poem about JavaScript.');When you stream to a browser via HTTP, you use Server-Sent Events (SSE). Here is the Express route pattern:
app.post('/chat/stream', async (req, res) => {
const { message } = req.body;
// Set SSE headers
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const stream = await client.messages.stream({
model: 'claude-opus-4-5',
max_tokens: 1024,
messages: [{ role: 'user', content: message }]
});
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta' &&
chunk.delta.type === 'text_delta') {
res.write(`data: ${JSON.stringify({ text: chunk.delta.text })}
`);
}
}
res.write('data: [DONE]
');
res.end();
});async function streamMessage(message, onChunk) {
const res = await fetch('/chat/stream', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ message })
});
const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value).split('
');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') return;
const { text } = JSON.parse(data);
onChunk(text);
}
}
}
}
// Usage
let output = '';
await streamMessage('Tell me a story', (chunk) => {
output += chunk;
document.getElementById('output').textContent = output;
});