# balena-request

> Balena HTTP client

Latest version **14.2.3** (published 2026-05-16) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install balena-request
pnpm add balena-request
yarn add balena-request
bun add balena-request
```

## Health

**Score 60/100 (C)** — status: active.

Positive: has types; no vulnerabilities; has provenance; high quality score.

Warnings: low downloads; no esm support.

## Facts

| | |
|---|---|
| Version | 14.2.3 |
| Published | 2026-05-16 |
| First published | 2018-10-18 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | bundled |
| Module format | CommonJS |
| Node | >=18.0.0 |
| Dependencies | 8 |
| Unpacked size | 248.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 2 |
| Author | Balena Ltd. |
| Maintainers | balena.io |
| Keywords | balena, request, http |

## Links

- npm: https://www.npmjs.com/package/balena-request
- Repository: https://github.com/balena-io-modules/balena-request
- Issues: https://github.com/balena-io-modules/balena-request/issues
- npm.io page: https://npm.io/package/balena-request

## Dependencies (8)

- [qs](https://npm.io/package/qs.md) ^6.9.4
- [tslib](https://npm.io/package/tslib.md) ^2.0.0
- [node-fetch](https://npm.io/package/node-fetch.md) ^2.7.0
- [balena-errors](https://npm.io/package/balena-errors.md) ^5.0.0
- [formdata-node](https://npm.io/package/formdata-node.md) ^6.0.3
- [progress-stream](https://npm.io/package/progress-stream.md) ^2.0.0
- [form-data-encoder](https://npm.io/package/form-data-encoder.md) ^4.0.2
- [fetch-readablestream](https://npm.io/package/fetch-readablestream.md) ^0.2.0

## Alternatives

- [launchdarkly-js-client-sdk](https://npm.io/package/launchdarkly-js-client-sdk.md) — 2.5M weekly downloads
- [@elastic/elasticsearch](https://npm.io/package/@elastic/elasticsearch.md) — 2.1M weekly downloads
- [@c8y/client](https://npm.io/package/@c8y/client.md) — 15.3K weekly downloads
- [@signaldb/maverickjs](https://npm.io/package/@signaldb/maverickjs.md) — 1.7K weekly downloads
- [@bbc/http-transport-cache](https://npm.io/package/@bbc/http-transport-cache.md) — 1.2K weekly downloads

## Recent versions

- 14.2.3 (latest) — 2026-05-16
- 14.2.4-build-renovate-chai-5-x-972f8593bc2911de0ddbc581337b3c2199d9ffe1-1 (build-renovate-chai-5-x) — 2026-05-16
- 14.2.3-build-renovate-balena-config-karma-4-0-x-5957eb452ce5b23e4b034e5ac265d59e0d324d3b-1 (build-renovate-balena-config-karma-4-0-x) — 2026-05-16
- 14.2.2-build-renovate-balena-errors-5-x-a5885be92a2abdec995ba28341ff8692f9ee5a71-1 (build-renovate-balena-errors-5-x) — 2026-05-12
- 14.2.2-build-renovate-major-8-jsdoc-to-markdown-975a167b44e05f41f00810d0712915c73072bfc2-1 (build-renovate-major-8-jsdoc-to-markdown) — 2026-04-24
- 14.2.2-build-renovate-major-9-jsdoc-to-markdown-25c16deeea53b8320da37ac62eb9ef7da2a238b8-1 (build-renovate-major-9-jsdoc-to-markdown) — 2026-04-24
- 14.2.2-build-renovate-major-17-sinon-1791655c166b53af9fd25dcac1c2ef156a9033ee-1 (build-renovate-major-17-sinon) — 2026-04-24
- 14.2.2-build-renovate-major-7-jsdoc-to-markdown-3cf66742a8e72bd2514b20bb319abb7150e3f0d1-1 (build-renovate-major-7-jsdoc-to-markdown) — 2026-04-24
- 14.2.2-build-renovate-major-10-mocha-c8da1c6d8abd12f6826048f223095fcd26bd4e0a-1 (build-renovate-major-10-mocha) — 2026-04-24
- 14.2.2-build-renovate-major-20-node-884d6dbfb9aa23e8038314f1c80c7935bbb82a5c-1 (build-renovate-major-20-node) — 2026-04-24
- 14.2.1-build-response-interceptors-2150d6669ae50eed667b32bc5d930d8568d14648-1 (build-response-interceptors) — 2026-04-24
- 14.2.0-build-export-error-types-c4e43ac0a7ac563a213f7685d4c1f7e4c5dbc1a9-1 (build-export-error-types) — 2026-03-24
- 14.1.7-build-url-canParse-af8fb6b626f2485d1db6e0ccbd6f47487a3d84c2-1 (build-url-canParse) — 2026-03-02
- 14.1.6-build-no-legacy-url-parse-83c95a2d9d630ddd51dba2ad906295dceec2ef4a-1 (build-no-legacy-url-parse) — 2026-02-12
- 14.1.6-build-renovate-major-22-node-920a76a2b3d24c53a3045134c67360c352d1e806-1 (build-renovate-major-22-node) — 2025-05-29
- … 337 more at https://npm.io/package/balena-request/versions

## README

balena-request
=============

> Balena HTTP client.

[![npm version](https://badge.fury.io/js/balena-request.svg)](http://badge.fury.io/js/balena-request)
[![dependencies](https://david-dm.org/balena-io-modules/balena-request.svg)](https://david-dm.org/balena-io-modules/balena-request.svg)
[![Build Status](https://travis-ci.org/balena-io-modules/balena-request.svg?branch=master)](https://travis-ci.org/balena-io-modules/balena-request)
[![Build status](https://ci.appveyor.com/api/projects/status/8qmwhh1vhm27otn4/branch/master?svg=true)](https://ci.appveyor.com/project/balena-io/balena-request/branch/master)
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/balena-io/chat)

Role
----

The intention of this module is to provide an exclusive client to make HTTP requests to the balena servers.

**THIS MODULE IS LOW LEVEL AND IS NOT MEANT TO BE USED BY END USERS DIRECTLY**.

Unless you know what you're doing, use the [balena SDK](https://github.com/balena-io/balena-sdk) instead.

Installation
------------

Install `balena-request` by running:

```sh
$ npm install --save balena-request
```

Documentation
-------------

The module returns a _factory function_ that you use to get an instance of the auth module.

It accepts the following params:

| Param | Type | Description |
| --- | --- | --- |
| options | <code>Object</code> | options |
| options.auth | <code>Object</code> | An instantiated [balena-auth](https://github.com/balena-io-modules/balena-auth) instance |
| options.debug | <code>boolean</code> | when set to `true` will log the request details in case of error. |
| options.isBrowser | <code>boolean</code> | set to `true` if the runtime is the browser. |
| options.interceptors | <code>Array&lt;Interceptor&gt;</code> | An initial array of interceptors |

**Example**
```js
var request = require('balena-request')({
	auth: auth,
	debug: false,
	isBrowser: false
})
```


* [request](#module_request)
    * [~getRequest(options)](#module_request..getRequest)
        * [~interceptors](#module_request..getRequest..interceptors) : <code>Array.&lt;Interceptor&gt;</code>
        * [~send(options)](#module_request..getRequest..send) ⇒ <code>Promise.&lt;Object&gt;</code>
        * [~stream(options)](#module_request..getRequest..stream) ⇒ <code>Promise.&lt;NodeJS.ReadableStream&gt;</code>
        * [~refreshToken(options)](#module_request..getRequest..refreshToken) ⇒ <code>Promise.&lt;String&gt;</code>
    * [~Interceptor](#module_request..Interceptor) : <code>object</code>

<a name="module_request..getRequest"></a>

### request~getRequest(options)
**Kind**: inner method of [<code>request</code>](#module_request)  
**Summary**: Creates a new balena-request instance.  

| Param | Type |
| --- | --- |
| options | <code>object</code> | 
| options.auth | <code>object</code> | 
| options.debug | <code>boolean</code> | 
| options.retries | <code>number</code> | 
| options.isBrowser | <code>boolean</code> | 
| options.interceptors | <code>array</code> | 


* [~getRequest(options)](#module_request..getRequest)
    * [~interceptors](#module_request..getRequest..interceptors) : <code>Array.&lt;Interceptor&gt;</code>
    * [~send(options)](#module_request..getRequest..send) ⇒ <code>Promise.&lt;Object&gt;</code>
    * [~stream(options)](#module_request..getRequest..stream) ⇒ <code>Promise.&lt;NodeJS.ReadableStream&gt;</code>
    * [~refreshToken(options)](#module_request..getRequest..refreshToken) ⇒ <code>Promise.&lt;String&gt;</code>

<a name="module_request..getRequest..interceptors"></a>

#### getRequest~interceptors : <code>Array.&lt;Interceptor&gt;</code>
The current array of interceptors to use. Interceptors intercept requests made
by calls to `.stream()` and `.send()` (some of which are made internally) and
are executed in the order they appear in this array for requests, and in the
reverse order for responses.

**Kind**: inner constant of [<code>getRequest</code>](#module_request..getRequest)  
**Summary**: Array of interceptor  
**Access**: public  
**Example**  
```js
request.interceptors.push(
	requestError: (error) ->
		console.log(error)
		throw error
)
```
<a name="module_request..getRequest..send"></a>

#### getRequest~send(options) ⇒ <code>Promise.&lt;Object&gt;</code>
This function automatically handles authorization with balena.

The module scans your environment for a saved session token. Alternatively, you may pass the `apiKey` option. Otherwise, the request is made anonymously.

Requests can be aborted using an AbortController (with a polyfill like https://www.npmjs.com/package/abortcontroller-polyfill
if necessary). This is not well supported everywhere yet, is on a best-efforts basis, and should not be relied upon.

**Kind**: inner method of [<code>getRequest</code>](#module_request..getRequest)  
**Summary**: Perform an HTTP request to balena  
**Returns**: <code>Promise.&lt;Object&gt;</code> - response  
**Access**: public  

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| options | <code>Object</code> |  | options |
| [options.method] | <code>String</code> | <code>&#x27;GET&#x27;</code> | method |
| options.url | <code>String</code> |  | relative url |
| [options.apiKey] | <code>String</code> |  | api key |
| [options.responseFormat] | <code>String</code> |  | explicit expected response format, can be one of 'blob', 'json', 'text', 'none'. Defaults to sniffing the content-type |
| [options.signal] | <code>AbortSignal</code> |  | a signal from an AbortController |
| [options.body] | <code>\*</code> |  | body |
| [options.timeout] | <code>number</code> |  | body |

**Example**  
```js
request.send
	method: 'GET'
	baseUrl: 'https://api.balena-cloud.com'
	url: '/foo'
.get('body')
```
**Example**  
```js
request.send
	method: 'POST'
	baseUrl: 'https://api.balena-cloud.com'
	url: '/bar'
	data:
		hello: 'world'
.get('body')
```
<a name="module_request..getRequest..stream"></a>

#### getRequest~stream(options) ⇒ <code>Promise.&lt;NodeJS.ReadableStream&gt;</code>
This function emits a `progress` event, passing an object with the following properties:

- `Number percent`: from 0 to 100.
- `Number total`: total bytes to be transmitted.
- `Number received`: number of bytes transmitted.
- `Number eta`: estimated remaining time, in seconds.

The stream may also contain the following custom properties:

- `String .mime`: Equals the value of the `Content-Type` HTTP header.

See `request.send()` for an explanation on how this function handles authentication, and details
on how to abort requests.

**Kind**: inner method of [<code>getRequest</code>](#module_request..getRequest)  
**Summary**: Stream an HTTP response from balena.  
**Returns**: <code>Promise.&lt;NodeJS.ReadableStream&gt;</code> - response  
**Access**: public  

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| options | <code>Object</code> |  | options |
| [options.method] | <code>String</code> | <code>&#x27;GET&#x27;</code> | method |
| options.url | <code>String</code> |  | relative url |
| [options.body] | <code>\*</code> |  | body |

**Example**  
```js
request.stream
	method: 'GET'
	baseUrl: 'https://img.balena-cloud.com'
	url: '/download/foo'
.then (stream) ->
	stream.on 'progress', (state) ->
		console.log(state)

	stream.pipe(fs.createWriteStream('/opt/download'))
```
<a name="module_request..getRequest..refreshToken"></a>

#### getRequest~refreshToken(options) ⇒ <code>Promise.&lt;String&gt;</code>
This function automatically refreshes the authentication token.

**Kind**: inner method of [<code>getRequest</code>](#module_request..getRequest)  
**Summary**: Refresh token on user request  
**Returns**: <code>Promise.&lt;String&gt;</code> - token - new token  
**Access**: public  

| Param | Type | Description |
| --- | --- | --- |
| options | <code>object</code> |  |
| options.baseUrl | <code>String</code> | relative url |

**Example**  
```js
request.refreshToken
	baseUrl: 'https://api.balena-cloud.com'
```
<a name="module_request..Interceptor"></a>

### request~Interceptor : <code>object</code>
An interceptor implements some set of the four interception hook callbacks.
To continue processing, each function should return a value or a promise that
successfully resolves to a value.

To halt processing, each function should throw an error or return a promise that
rejects with an error.

**Kind**: inner typedef of [<code>request</code>](#module_request)  
**Properties**

| Name | Type | Description |
| --- | --- | --- |
| [request] | <code>function</code> | Callback invoked before requests are made. Called with the request options, should return (or resolve to) new request options, or throw/reject. |
| [response] | <code>function</code> | Callback invoked before responses are returned. Called with the response, should return (or resolve to) a new response, or throw/reject. |
| [requestError] | <code>function</code> | Callback invoked if an error happens before a request. Called with the error itself, caused by a preceeding request interceptor rejecting/throwing an error for the request, or a failing in preflight token validation. Should return (or resolve to) new request options, or throw/reject. |
| [responseError] | <code>function</code> | Callback invoked if an error happens in the response. Called with the error itself, caused by a preceeding response interceptor rejecting/throwing an error for the request, a network error, or an error response from the server. Should return (or resolve to) a new response, or throw/reject. |


Support
-------

If you're having any problem, please [raise an issue](https://github.com/balena-io-modules/balena-request/issues/new) on GitHub and the balena team will be happy to help.

Tests
-----

Run the test suite by doing:

```sh
$ npm test
```

Contribute
----------

- Issue Tracker: [github.com/balena-io-modules/balena-request/issues](https://github.com/balena-io-modules/balena-request/issues)
- Source Code: [github.com/balena-io-modules/balena-request](https://github.com/balena-io-modules/balena-request)

Before submitting a PR, please make sure that you include tests, and that [coffeelint](http://www.coffeelint.org/) runs without any warning:

```sh
$ gulp lint
```

License
-------

The project is licensed under the Apache 2.0 license.

---
_Source: https://npm.io/package/balena-request · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
