Learn how to consume streaming API responses using Server-Sent Events
Perplexica’s Search API supports streaming responses, allowing you to receive results incrementally as they’re generated. This provides a better user experience by displaying partial results immediately rather than waiting for the complete response.
When streaming is enabled, the API returns a stream using Server-Sent Events (SSE) with Content-Type: text/event-stream. Each line in the stream contains a complete, valid JSON object.
Sent multiple times with chunks of the generated answer:
{"type":"response","data":"Perplexica is an "}{"type":"response","data":"innovative, open-source "}{"type":"response","data":"AI-powered search engine..."}
Here’s what a complete streaming response looks like:
{"type":"init","data":"Stream connected"}{"type":"sources","data":[{"content":"...","metadata":{"title":"...","url":"..."}}]}{"type":"response","data":"Perplexica is an "}{"type":"response","data":"innovative, open-source "}{"type":"response","data":"AI-powered search engine..."}{"type":"done"}
Here are examples of how to consume the streaming API in different languages:
const response = await fetch('http://localhost:3000/api/search', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ chatModel: { providerId: '550e8400-e29b-41d4-a716-446655440000', key: 'gpt-4o-mini' }, embeddingModel: { providerId: '550e8400-e29b-41d4-a716-446655440000', key: 'text-embedding-3-large' }, sources: ['web'], query: 'What is Perplexica', stream: true })});const reader = response.body.getReader();const decoder = new TextDecoder();while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split('\n').filter(line => line.trim()); for (const line of lines) { const message = JSON.parse(line); switch (message.type) { case 'init': console.log('Stream connected'); break; case 'sources': console.log('Sources:', message.data); break; case 'response': process.stdout.write(message.data); break; case 'done': console.log('\nStream complete'); break; } }}
Each line in the stream is a complete JSON object. Make sure to parse each line separately rather than treating the entire stream as a single JSON document.