# Streaming web request

{% hint style="info" %}
**Beta feature**

The Streaming web request action node is currently in **beta**. Functionality may change in future updates.
{% endhint %}

The Streaming web request action node sends an HTTP request and processes the response incrementally as chunks arrive, rather than waiting for the complete response. This lets you update the UI in real time as data is received — for example, displaying AI-generated text word by word as a language model streams its response, instead of making the user wait for the full reply.

The node is designed for cases where a user is watching the output as it arrives. A typical use case is integrating with AI APIs that return streaming responses via Server-Sent Events (SSE), but it works with any API that sends a chunked or streamed response.

### Request settings

The request configuration is the same as on the [Web request](/library/action-nodes/web-request.md) action node: **Base URL**, **Path**, **Path Parameters**, **Query Parameters**, **Request Headers**, **Authorization**, **Method**, **Body Type**, **Body Content**, and **Content Type** all work the same way. See the Web request page for details on each setting.

As on the Web request action node, the **Timeout** setting controls how long the node waits for the response to complete. The default is `30 000` ms.

### Chunk handler

The chunk handler is a JavaScript function that runs each time a chunk of data is received from the streaming response. It is authored in the standard function editor and is where you define how incoming data should be parsed and processed.

#### Built-in function params

The following parameters are available automatically in the chunk handler:

| Parameter          | Description                                                                                                                                                                                                                                                                                                          |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rawChunk`         | The raw chunk of data received from the stream, as a string.                                                                                                                                                                                                                                                         |
| `buffer`           | A persistent array that survives across chunk handler invocations. Use it to accumulate partial data that spans chunk boundaries — for example, an incomplete line that continues in the next chunk.                                                                                                                 |
| `memory`           | A persistent Map for storing custom values between chunk handler invocations. Use it to keep track of state that does not fit the `buffer` array — for example, counters, flags, or accumulated results. Values set with `memory.set(key, value)` in one invocation are available via `memory.get(key)` in the next. |
| `responseCode`     | The HTTP status code of the response.                                                                                                                                                                                                                                                                                |
| `responseHeaders`  | The response headers.                                                                                                                                                                                                                                                                                                |
| `generateObjectId` | A utility function for generating object IDs.                                                                                                                                                                                                                                                                        |
| `DOMParser`        | The standard DOMParser, available for parsing XML or HTML content.                                                                                                                                                                                                                                                   |

In addition to the built-in params, you can add custom function params from the left pane — action data, app data, app variables, and other data sources — just like in any other function editor in Appfarm Create.

#### How the chunk handler works

The chunk handler is called once for each chunk the server sends. A chunk is a fragment of the response body — it may contain a complete message, part of a message, or multiple messages depending on the streaming protocol and network conditions.

Because chunks may split data at arbitrary points, the built-in `buffer` array is provided for reassembling data across invocations. A typical pattern is to push the raw chunk onto the buffer, join and split on a delimiter (such as a newline), and keep any incomplete trailing fragment in the buffer for the next call.

{% tabs %}
{% tab title="Example: parsing SSE from an AI API" %}
This example parses Server-Sent Events from an AI Messages API. Each SSE event is a line starting with `data:` followed by a JSON payload. The handler extracts text deltas and passes each one to an action called `updateStreamingResponse`.

```javascript
buffer.push(rawChunk);
const combined = buffer.join('');
const lines = combined.split('\n');
buffer.length = 0;
buffer.push(lines.pop()); // keep incomplete last line

lines
  .filter(line => line.startsWith('data: '))
  .map(line => line.slice(6).trim())
  .filter(jsonStr => jsonStr && jsonStr !== '[DONE]')
  .map(jsonStr => {
    try { return JSON.parse(jsonStr); }
    catch (e) { return null; }
  })
  .filter(parsed =>
    parsed &&
    parsed.type === 'content_block_delta' &&
    parsed.delta?.type === 'text_delta' &&
    parsed.delta?.text
  )
  .map(parsed => () => updateStreamingResponse({ input: parsed.delta.text }))
  .reduce((chain, fn) => chain.then(fn), Promise.resolve());
```

{% endtab %}
{% endtabs %}

### Actions

The **Actions** section on the Streaming web request node lets you wire up actions that the chunk handler can call during processing. Each entry has two settings: **Function Name**, which is the name you use to call the action from within the chunk handler, and **Action**, which selects the Appfarm action to run.

Invoking an action from the chunk handler returns a Promise that resolves when the action finishes. To execute actions in sequence safely, see the [Promise composition guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#composition). For actions with parameters, select **Code Function Param** on each action param you want to pass from code, then call the function with an object of key/value pairs. For example, if the function name is `updateStreamingResponse` and the action has a code function param named `input`:

```javascript
updateStreamingResponse({ input: "some text" })
  .then(() => console.log('done!'))
  .catch(console.error)
```

Actions are called explicitly from within the chunk handler — they do not run automatically. This gives you full control over when and how often each action is invoked. In the SSE example above, the action is called once per text delta, and the calls are chained sequentially using `.reduce()` to ensure they execute in order.

### Other settings

| Property                     | Description                                                                                                                                                                                                                                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Disabled**                 | Disables the action node. The node is skipped when the action runs.                                                                                                                                                                                                                         |
| **Disabled in Dev and Test** | Disables the action node in the Development and Test environments only.                                                                                                                                                                                                                     |
| **Send from Client**         | Sends the request directly from the client instead of routing it through the Appfarm server. When enabled, the hostname must be added to **Allowed web request targets** in **Environment Config**, and [Secrets](/reference/security/secrets.md) are not available for use in the request. |

### Properties

The request-side properties (**Base URL**, **Path**, **Path Parameters**, **Query Parameters**, **Request Headers**, **Authorization**, **Method**, **Timeout**, **Body Type**, **Body Content**, **Content Type**) are the same as on the [Web request](/library/action-nodes/web-request.md) action node. The following properties are specific to the Streaming web request:

| Property          | Description                                                                                                   |
| ----------------- | ------------------------------------------------------------------------------------------------------------- |
| **Chunk Handler** | A JavaScript function that runs on each chunk of the streaming response. See [Chunk handler](#chunk-handler). |
| **Actions**       | Actions that can be called from within the chunk handler. See [Actions](#actions).                            |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.appfarm.io/library/action-nodes/streaming-web-request.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
