> ## Documentation Index
> Fetch the complete documentation index at: https://docs.requestly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# rq.variables (All scopes)

> Complete reference for the rq.variables object in Requestly scripts, which reads a variable from whichever scope defines it and writes to the runtime scope.

The `rq.variables` object is the one accessor that looks in **every** scope. Use it when you want a value and do not care which scope holds it, which is most of the time. The scope specific objects ([`rq.environment`](https://docs.requestly.com/api-client/rq-api-reference/rq-environment), [`rq.collectionVariables`](https://docs.requestly.com/api-client/rq-api-reference/rq-collection-variables), [`rq.globals`](https://docs.requestly.com/api-client/rq-api-reference/rq-globals), [`rq.iterationData`](https://docs.requestly.com/api-client/rq-api-reference/rq-iteration-data)) each read one scope only.

Reads search the scopes in this order, and the first one that defines the name wins:

```text theme={null}
runtime  >  data file (Collection Runner)  >  environment  >  collection (nearest first)  >  global
```

A disabled variable, or one you removed earlier in the same run, is skipped, so the next scope down shows through.

**Writes always go to the runtime scope**, whichever scope the value originally came from. `rq.variables.set` never edits your environment, collection, or global variables. To change one of those, use its own object.

## Methods

### `rq.variables.get(key)`

Returns the value of a variable from the first scope that defines it.

**Parameters:**

* `key` (string): The variable's name

**Returns:** The value, or `undefined` if no scope has an enabled variable with that name. A number, boolean or array variable comes back as that type, and a data file value keeps the type the file gave it. A variable you set earlier in the same script comes back as `set` stored it.

**Example:**

```javascript theme={null}
// Finds the token wherever it lives: something you set earlier in this run,
// a data file column, the active environment, the collection, or globals.
const token = rq.variables.get("authToken");
```

### `rq.variables.set(key, value, type?)`

Creates or updates a **runtime** variable.

**Parameters:**

* `key` (string): The variable's name. It must not be empty.
* `value` (any): The value to store. A runtime variable that already exists converts the value to its type: `set("count", "42")` on a number variable stores `42`. A new variable keeps the value exactly as you pass it. `null` or `undefined` removes the variable, the same as `unset(key)`.
* `type` (string, optional): The type to give the variable before the value is stored: `"string"`, `"number"`, `"boolean"`, `"array"`, `"object"` or `"any"`. You can also pass `{ type }`.

See [How values are saved](#how-values-are-saved) for what the next request reads.

**Example:**

```javascript theme={null}
rq.variables.set("requestId", rq.$randomUUID());
```

### `rq.variables.has(key)`

Checks whether any scope has a variable with this name that is enabled.

**Parameters:**

* `key` (string): The variable's name

**Returns:** `true` if some scope has the variable and it is enabled, otherwise `false`.

**Example:**

```javascript theme={null}
if (!rq.variables.has("authToken")) {
  console.log("No auth token in any scope, logging in first");
}
```

### `rq.variables.unset(key)`

Removes a runtime variable, so `get` reads the name from the next scope down. A disabled variable is left alone. A value you typed into your runtime variables yourself is not deleted, and later requests read it again.

**Parameters:**

* `key` (string): The variable's name. It must not be empty.

**Example:**

```javascript theme={null}
rq.variables.unset("requestId");
```

### `rq.variables.clear()`

Removes every runtime variable, disabled ones included, so `get` reads each name from the other scopes. Values you typed into your runtime variables yourself are not deleted, and later requests read them again.

**Example:**

```javascript theme={null}
rq.variables.clear();
```

### `rq.variables.toObject()`

Returns every enabled variable the script can read as one object of names and values. When scopes define the same name, the scope `get` searches first wins.

**Returns:** An object such as `{ baseUrl: "https://api.example.com", authToken: "abc" }`. Each value has the type `get` returns for it.

**Example:**

```javascript theme={null}
const all = rq.variables.toObject();
console.log("Variables in play:", Object.keys(all).length);
```

### `rq.variables.replaceIn(template)`

Replaces each `{{name}}` in a template with the value of that variable, using the same search order as `get`.

**Parameters:**

* `template` (string, object or array): Text containing `{{name}}` references. In an object or an array, every string inside is replaced.

**Returns:** The template with the references replaced. A value that is not text is written the way JavaScript's `String()` writes it, so an array becomes `a,b`. A name no scope defines stays exactly as written, so you can see what was missing. A dynamic variable such as `{{$guid}}` also stays as written: call [`rq.$guid()`](https://docs.requestly.com/api-client/environments-and-variables/dynamic-variables) and build the string yourself. Each reference is replaced once, so a `{{name}}` inside a value stays as written.

**Example:**

```javascript theme={null}
const url = rq.variables.replaceIn("{{baseUrl}}/users/{{userId}}");
// "https://api.example.com/users/42"
```

### `rq.variables.toObjectResolved(scope?, overrides?)`

Returns a plain copy of `rq.variables`, the same as `toJSON()`, with every `{{name}}` inside it replaced. For a plain object of names and values, use `toObject()`.

**Parameters:**

* `scope` (object, optional): The object whose `replaceIn` replaces the references. Defaults to `rq.variables`, which reads every scope.
* `overrides` (array of objects, optional): Objects whose properties are copied onto the result, in order.

**Returns:** An object with `id`, `values` and `mutations`.

**Example:**

```javascript theme={null}
const resolved = rq.variables.toObjectResolved();
resolved.values.forEach((item) => console.log(item.key, item.value));
```

### `rq.variables.toJSON()`

Returns a plain copy of `rq.variables`. `JSON.stringify(rq.variables)` uses it.

**Returns:** An object with:

* `id`: The same as `rq.variables.id`
* `values`: The runtime variables, as an array of `{ key, value, type }` items, with `disabled: true` on a disabled variable. An array variable's `value` is its JSON text.
* `mutations`: The changes this script recorded, as `{ stream, compacted, autoCompact }`

**Example:**

```javascript theme={null}
console.log(JSON.stringify(rq.variables));
```

### `rq.variables.syncVariablesFrom(object, track?)`

Copies the names and values of a plain object into the runtime variables. An existing runtime variable gets the new value, converted to its type, and a new name becomes a new runtime variable. Variables the object does not name are kept. The changes are saved the same way as `set`, but are not recorded in `mutations`.

**Parameters:**

* `object` (object): The names and values to copy in
* `track` (boolean, optional): Set to `true` to get back what changed

**Returns:** With `track` set to `true`, an object that maps each new name to `"created"` and each name whose value changed to `"updated"`. A name whose value did not change is not listed. Without `track`, `undefined`.

**Example:**

```javascript theme={null}
// "retries" exists and "region" does not
const changes = rq.variables.syncVariablesFrom({ region: "eu", retries: 5 }, true);
console.log(changes); // { region: "created", retries: "updated" }
```

### `rq.variables.syncVariablesTo(object?)`

Copies every runtime variable, disabled ones included, into a plain object. Variables from the other scopes are not copied.

**Parameters:**

* `object` (object, optional): The object to copy into. Any key in it that the runtime variables do not hold is deleted from it. Without it, a new object is used.

**Returns:** The object, with one property per variable. Each value has the type `get` returns for it.

**Example:**

```javascript theme={null}
const copy = rq.variables.syncVariablesTo();
console.log(Object.keys(copy));
```

### `rq.variables.values`

The runtime variables, as a list. `get` also reads the other scopes, but their variables are not in this list. Unlike `get`, `has` and `toObject`, the list includes disabled variables.

Each item is one variable with `key`, `value`, `type` and `disabled`. Call the item's `get()` to read its value as its type, since an array variable's `value` is its JSON text, and its `set(value)` to change it.

The list has these methods:

* **Read:** `one(key)` returns the variable with that name, and `get(key)` its value. `has(key)` checks whether the list holds that name. `count()` returns the number of variables, `all()` an array of them, `idx(index)` the one at a position, and `indexOf(key)` its position, or `-1`. `toObject()` returns an object of names and values, and `toJSON()` an array of plain `{ key, value, type }` items.
* **Loop:** `each(fn)`, `map(fn)`, `filter(fn)`, `find(fn)` and `reduce(fn, initial)` work like the array methods of the same name. `fn` receives each variable and its position.
* **Change:** `add({ key, value, type, disabled })` adds a variable. `upsert({ key, value, type, disabled })` updates the variable with that name, or adds it when there is none. `remove(key)` removes the variable with that name, and `remove(fn)` removes every variable `fn` returns `true` for. `clear()` removes every variable.
* **Text:** `replace(text)` replaces each `{{name}}` in `text` with the list's value for that name.
* **Copy:** `syncFromObject(object, track?, prune?)` works like `syncVariablesFrom`, and with `prune` set to `true` it also removes the variables the object does not name. `syncToObject(object?)` works like `syncVariablesTo`.

Changes made through `values` are saved the same way as `set`, but are not recorded in `mutations`.

**Example:**

```javascript theme={null}
rq.variables.values.each((variable) => {
  console.log(variable.key, variable.get(), variable.disabled === true);
});
rq.variables.values.upsert({ key: "region", value: "eu" });
```

### `rq.variables.id`

A random id, new each time a script runs.

**Example:**

```javascript theme={null}
console.log(rq.variables.id);
```

### `rq.variables.mutations`

A record of the `set` and `unset` calls this script made on `rq.variables`, in order. Recording is on from the start of the script. `clear()` records an `unset` for each variable it removes, and `applyMutation` records the call it makes. Changes made through `values` or `syncVariablesFrom` are not recorded.

* `stream` (array): One entry per call: `[key, value]` for `set` and `[key]` for `unset`. `value` is what you passed, before any conversion.
* `compacted` (object): The last change to each name, filled by `compact()` or by `autoCompact`
* `count()`: Returns the number of recorded changes
* `compact()`: Keeps only the last change to each name, moving the entries from `stream` into `compacted`
* `applyOn(target)`: Makes the recorded changes again on another object, such as `rq.environment`

**Example:**

```javascript theme={null}
rq.variables.set("token", "abc");
rq.variables.unset("oldToken");
console.log(rq.variables.mutations.stream); // [["token", "abc"], ["oldToken"]]

// Save the same changes in the active environment
rq.variables.mutations.applyOn(rq.environment);
```

### `rq.variables.enableTracking(options?)`

Starts recording `set` and `unset` calls in `mutations`. Recording is already on when a script starts, so calling this does nothing until you call `disableTracking()`. After that, it starts a new, empty record.

**Parameters:**

* `options` (object, optional): `{ autoCompact: true }` keeps only the last change to each name, in `mutations.compacted`

**Example:**

```javascript theme={null}
rq.variables.disableTracking();
rq.variables.enableTracking({ autoCompact: true });
rq.variables.set("page", 1);
rq.variables.set("page", 2);
console.log(rq.variables.mutations.compacted); // { page: ["page", 2] }
```

### `rq.variables.disableTracking()`

Stops recording changes in `mutations`. What was already recorded stays in `mutations`.

**Example:**

```javascript theme={null}
rq.variables.disableTracking();
```

### `rq.variables.applyMutation(instruction, key, value?)`

Makes one change, named by `instruction`: `"set"` calls `set(key, value)` and `"unset"` calls `unset(key)`, so the change goes to the runtime variables. Any other instruction does nothing.

**Parameters:**

* `instruction` (string): `"set"` or `"unset"`
* `key` (string): The variable's name
* `value` (any, optional): The value, for `"set"`

**Example:**

```javascript theme={null}
rq.variables.applyMutation("set", "region", "eu");
```

### `rq.variables.addLayer(list)`

Adds a list of variables for `get`, `has`, `toObject` and `replaceIn` to read last, after the global variables. Writes still go to the runtime variables only. Every scope's `values` is already read, so adding one changes nothing.

**Parameters:**

* `list`: Another object's `values`, such as `rq.globals.values`

**Example:**

```javascript theme={null}
rq.variables.addLayer(rq.globals.values);
rq.variables.get("appVersion"); // the same value as before
```

## How values are saved

Runtime values are saved the same way as [`rq.environment`](https://docs.requestly.com/api-client/rq-api-reference/rq-environment#how-values-are-saved) values, with one difference: they last for the session only. Within one script, `get` returns the value `set` stored, and the next request reads the saved form.

A value you set from a script is never saved back to your runtime variables list, so a reload restores whatever you typed there yourself. If you need a value to survive, write it to the environment, the collection, or globals instead.

See [Typed variables](https://docs.requestly.com/api-client/rq-api-reference/rq-environment.md#typed-variables) for how a variable's type converts the value you set, and [Disabled variables](https://docs.requestly.com/api-client/rq-api-reference/rq-environment.md#disabled-variables) for how disabled variables behave.

## Common Use Cases

### Read a value without knowing its scope

The usual reason to reach for `rq.variables`. The same script keeps working after someone moves a variable from the collection to the environment:

```javascript theme={null}
const baseUrl = rq.variables.get("baseUrl");
const apiKey = rq.variables.get("apiKey");
console.log(`Calling ${baseUrl} with key ending ${String(apiKey).slice(-4)}`);
```

### Fail early with a clear message

```javascript theme={null}
for (const name of ["baseUrl", "authToken", "tenantId"]) {
  if (!rq.variables.has(name)) {
    throw new Error(`Missing variable: ${name}`);
  }
}
```

### Pass a value to the next request

Runtime scope is the right home for a value that only bridges one request to the next:

```javascript theme={null}
// In a post-response script
const body = rq.response.json();
rq.variables.set("orderId", body.id);

// The next request can use {{orderId}} in its URL, headers, or body.
```

### Build a URL from a template

```javascript theme={null}
const endpoint = rq.variables.replaceIn("{{baseUrl}}/tenants/{{tenantId}}/orders");
const response = await rq.sendRequest({ url: endpoint, method: "GET" });
```

### Override a data file column for one run

A value you set from a script beats a column of the same name in the Collection Runner's data file, which is what lets a pre-request script refresh an expiring token seeded from the file:

```javascript theme={null}
if (isExpired(rq.variables.get("authToken"))) {
  rq.variables.set("authToken", await fetchFreshToken());
}
```

## Choosing between `rq.variables` and a scope specific object

| Use | When |
| :- | :- |
| `rq.variables.get` | You want the value, wherever it is defined. |
| `rq.environment.get` | You specifically want the environment's copy, ignoring anything that shadows it. |
| `rq.variables.set` | The value is temporary and only needs to last this session. |
| `rq.environment.set`, `rq.collectionVariables.set`, `rq.globals.set` | The value should be saved and still be there tomorrow. |

## Related Documentation

* [Pre-request & Post-response Scripts](https://docs.requestly.com/api-client/scripts.md)
* [Variable Precedence](https://docs.requestly.com/api-client/environments-and-variables/variable-precedence.md)
* [Runtime variables](https://docs.requestly.com/api-client/environments-and-variables/runtime-variables.md)
* [Dynamic variables](https://docs.requestly.com/api-client/environments-and-variables/dynamic-variables.md)
* [rq.environment Object](https://docs.requestly.com/api-client/rq-api-reference/rq-environment.md)
* [rq.collectionVariables Object](https://docs.requestly.com/api-client/rq-api-reference/rq-collection-variables.md)
* [rq.globals Object](https://docs.requestly.com/api-client/rq-api-reference/rq-globals.md)
* [rq.iterationData Object](https://docs.requestly.com/api-client/rq-api-reference/rq-iteration-data.md)
* [rq.vault Object](https://docs.requestly.com/api-client/rq-api-reference/rq-vault.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.