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;
}); Before moving on, make sure you can answer these without looking: