Skip to main content

Scripts in Requestly allow you to extend and customize your API requests and responses dynamically using JavaScript. These scripts enable you to manipulate requests before they are sent (Pre-request scripts) or process responses after they are received (Post-response scripts). With access to the full request and response objects, you can achieve advanced automation, validations, and transformations.

Pre-Request Scripts

Pre-Request Scripts run before the API request is sent to the server. They allow you to modify request attributes, such as headers, body, query parameters, or even the URL. Pre Scripts are useful for adding authentication tokens, generating timestamps, or altering the request dynamically based on certain conditions. Let’s try to understand the workings of pre-script using easy-to-follow examples. Auto Increment Page Numbers Let’s assume you have an endpoint that takes page number as query parameter, we use environment variable {{page_number}} to get value of page number.
We can get current page number from environment variables and set it back with an increment.
Now every time you click the Send button of this request it would send incremented page number. Test APIs by Randomising Values During development hitting an API with new data every time can be a pain, we can use Pre-Script to randomise the values and call the same API without getting duplicate entry error. Let’s setup our request with body as follows:
We will use below pre-script to create random values and update them in environment variables.
You can also use pre-script to generate access tokens, validate the requests, generate some random data for the request. You can also access elements of the request, collection variables and environment variables, checkout Requestly’s JavaScript API.

Post-Response Scripts

Post-Response Scripts run after the API response is received. They allow you to process response data, validate outputs, or log details for debugging. Post Scripts are useful for transforming the response body, validating response codes, or storing results for further use. Let’s try to understand the working of post script using easy to follow examples. Validate Response Code
We can also fetch and set API Keys or auth tokens, id, and other data from response of an API and use it in other APIs. You can access elements of the request, response, collection variables and environment variables, checkout Requestly’s JavaScript API.

Viewing Console Logs from Scripts

You can use console.log() or console.error() in your Pre-Request and Post-Response Scripts to debug your logic and inspect values at runtime. The logs appear in Requestly’s built-in DevTools panel and are tagged with #script so you can filter them quickly.
1

Open DevTools

Click the DevTools button in the application footer at the bottom of the window. The panel docks to the bottom of the workspace with a Console tab selected by default.To see logs for just one request, send the request and open the Debug tab in the response area instead. It shows DevTools scoped to that request’s most recent execution.
2

Filter logs from your scripts

In the Console tab’s search box, type #script to show only logs produced by your Pre-Request and Post-Response Scripts and hide system events and network summaries.
For everything DevTools can show you, including the Network tab and per-request inspection, see the DevTools page.

Requestly JavaScript API rq

Requestly provides a robust set of JavaScript properties and methods to interact with API requests, responses, environments, and global variables. The rq object is available in all pre-request and post-response scripts, giving you full control over your API workflow.

Available Objects

The Requestly JavaScript API consists of the following main objects:

rq.request

Access and manipulate API request details including method, headers, body, URL, and query parameters. Use this in both pre-request and post-response scripts to read or modify request data. Quick Example:
View complete rq.request documentation →

rq.response

Access API response details including body, headers, status code, and response time. Primarily used in post-response scripts to process and validate API responses. Quick Example:
View complete rq.response documentation →

rq.sendRequest

Send an HTTP request from inside a script and read its response. Use it to fetch a token before the main request runs, call a second endpoint, or poll a status URL. Available in both pre-request and post-response scripts. Quick Example:
View complete rq.sendRequest documentation →

rq.execution

Control how a request runs: read where it sits in your collection, skip it, set which request the collection runner goes to next, and run another saved request. Quick Example:
View complete rq.execution documentation →

rq.variables

Read a variable from whichever scope defines it, and write temporary values for the current session. This is the object to reach for when you want a value and do not care where it lives. Quick Example:
View complete rq.variables documentation →

rq.environment

Manage environment-specific variables dynamically. Environment variables are scoped to a specific environment (dev, staging, production) and can be used across multiple requests. Quick Example:
View complete rq.environment documentation →

rq.collectionVariables

Manage collection-scoped variables. Collection variables are only accessible within requests that belong to a specific collection and persist across all environments. Quick Example:
View complete rq.collectionVariables documentation →

rq.globals

Manage global variables accessible across all collections and environments. Use for truly universal configuration and state. Quick Example:
View complete rq.globals documentation →

rq.test

Write tests to validate API responses and ensure your APIs work as expected. Tests help automate quality assurance in post-response scripts. Quick Example:
View complete rq.test documentation →

rq.expect

Write assertions for API testing using the powerful Chai.js assertion library. Use with rq.test to validate response data. Quick Example:
View complete rq.expect documentation →

rq.info

Access execution metadata including request name, iteration index, and event name. Useful for tracking progress in collection runs and implementing iteration-specific logic. Quick Example:
View complete rq.info documentation →

rq.iterationData

Access data from CSV or JSON files during collection runs. Each iteration receives different data from the file, enabling data-driven testing. Quick Example:
View complete rq.iterationData documentation →

rq.visualizer

Render a custom visualization of the response - a chart, a table, or formatted HTML - shown behind a Visualize button in the response body. Available in both pre-request and post-response scripts. Quick Example:
View complete rq.visualizer documentation →

Using Dynamic Variables in Scripts

Requestly provides dynamic variables, which are built in values that automatically generate common data such as timestamps, UUIDs, and random values. You can access them in scripts using the rq.$variableName() syntax. Quick Example:
Common Dynamic Variables:
  • rq.$randomUUID() - Generate unique identifiers
  • rq.$timestamp() - Current Unix timestamp
  • rq.$isoTimestamp() - ISO 8601 timestamp
  • rq.$randomInt() - Random integer
  • rq.$randomEmail() - Random email address
  • rq.$randomFirstName() - Random first name
  • rq.$randomCompanyName() - Random company name
With Arguments:
View complete Dynamic Variables documentation →

Chaining API requests

When one request depends on the output of another, use a post-response script on the first request to extract the values you need, then reference them from the second request using {{variable_name}} placeholders. The same pattern covers auth-token flows, “create then update” sequences, and conditional logic that decides what the next call should send. The flow has three pieces:
  1. Post-response script on the prerequisite request. Parse the response and write the values into a variable scope.
  2. Reference the variables from the next request’s URL, headers, query params, or body using {{variable_name}} syntax. See Using variables in API requests.
  3. Run the requests in order, either manually or by adding them to a collection and using the Collection Runner.

Example: pass dynamic data from one request to the next

A collection with two requests: Get Users followed by Add User. The post-response script on Get Users checks whether the target user already exists. If they don’t, it stages fresh data for the second request to consume. Post-response script on Get Users:
Request body on Add User:
When the collection runs, Requestly substitutes {{new_user_name}} and {{new_user_email}} with whatever the post-response script wrote. Anything the next request needs (an id from a POST to feed a follow-up PATCH, an auth token from a login call, an order number returned by a checkout step) follows the same shape.

Picking a variable scope

For values that exist only to bridge one request to the next, prefer runtime scope. It stays local to your device and does not pollute your saved environment with one-off state. Reach for environment or collection scope when the value (an auth token, a tenant id) is meaningful beyond the immediate chain. For the full per-scope reference, see Runtime variables, rq.variables, rq.environment, rq.collectionVariables, and rq.globals.

Sharing code between scripts

The section above passes data between scripts through a variable scope. To share code — a helper function you want every request in a collection to call — you do not need a variable, and you do not need to repeat the helper in each request. Every script in one run shares a single scope: the collection-level script, each folder-level script, the request’s own pre-request script, and its post-response script.

Example: define a helper once, call it from every request

Collection pre-request script:
Request pre-request script:
The post-response script of that same request can call auth too — the shared scope spans the whole request, not just the pre-request phase.

Why there is no var in front of auth

The missing keyword is doing the work, and the reason is ordinary JavaScript scoping. Each script runs wrapped in its own function. A var, let, const, function or class declaration is scoped to the function it appears in, so it is discarded as soon as that script finishes — a later script has no way to reach it. An assignment with no keyword does not declare anything. auth = { ... } sets a property on the global object, and that global object is the one thing every script in the run shares, so the value outlives the script that created it:
Writing globalThis.auth = { ... } does exactly the same thing and says so explicitly. Prefer it if a bare assignment reads as a mistake to you or your reviewers.
var auth = { ... } raises no error of its own. The collection script runs fine and the request script simply sees auth as undefined, so the failure surfaces later as a TypeError on the first call. If a shared helper reads as undefined, check for a var, let, or const in front of it first.

What the shared scope does and does not keep

  • It lasts for one run. Every request in a Collection Runner run shares it. Sending a single request from the editor is a run of one.
  • A script timeout discards it. If a script is killed for exceeding its time budget, the scope is thrown away and the next run starts clean.
  • It holds values, not saved state. Nothing here is persisted. For data that must outlive the run, write it to a variable scope as described above.
To share code across collections — or to keep it in one place and version it — author a Custom Package instead and require() it. See Import packages into your scripts.

Encoding request payloads

Some APIs require the body to be transformed before it goes on the wire, for example Base64-encoding a JSON envelope. Compute the transformed value in a pre-request script and write it back with rq.request.body.update(value) (or plain assignment, rq.request.body = value) — the value is sent exactly as your script produced it, byte for byte, with no variable resolution applied to it. Headers, query parameters, the URL, and the method are writable the same way. See rq.request for the full mutation surface, and Signing requests when the transformation is a signature.

Base64 encoding with Buffer

require('buffer') is available in scripts. It is the recommended path because it handles non-ASCII characters correctly. Pre-request script:
The request is sent with the encoded string as its body. Set Content-Type to whatever the server expects — an explicit header row always wins, typically text/plain or application/octet-stream for a raw Base64 string, or application/json if the encoded value is wrapped inside a JSON envelope.

Base64 encoding with btoa

btoa and atob are available as globals. They are convenient when the payload is plain ASCII:
Prefer Buffer over btoa when the payload may contain non-ASCII characters. btoa throws on anything outside the Latin-1 range.

Decoding a Base64 response

Mirror the encoding pattern in a post-response script:
When the response itself is binary (an image, PDF, or archive), Requestly already hands you the body as Base64. Check rq.response.bodyEncoding to tell binary from text before decoding:

Signing requests

Some APIs require a signature computed over the request body. Compute it in a pre-request script and write the body and the signature header onto the request together. The body is sent exactly as your script produced it, byte for byte, with no variable resolution applied afterwards, so the signature always matches the payload it was computed over. You do not need to stage the signed value in a variable and reference {{signature}} from the request. That older pattern can send a signature computed for a previous payload.

HMAC signatures

Node’s crypto module is available via require('crypto'), and HMAC works in both Safe and Developer script modes:
The same module covers hashes (createHash) and symmetric ciphers.

RS256 and other asymmetric signatures

The asymmetric functions of require('crypto') (createSign, createVerify, generateKeyPair and their siblings) are not available in Safe mode, which is the default. Use a signing library written in pure JavaScript instead: it does not rely on platform crypto, so it behaves the same in both modes. Install jsrsasign from npm (available in the desktop app), then sign in a pre-request script:
The private key is a PEM string, in either PKCS#8 (-----BEGIN PRIVATE KEY-----) or PKCS#1 (-----BEGIN RSA PRIVATE KEY-----) form. PS256 and HS256 work the same way.
Do not paste a library’s source into an environment variable and eval() it. require() loads the library directly. A megabyte of source held in a variable is awkward to edit, easy to truncate, and travels with every export of that environment.

Keys, and what signing costs

Keep private keys and signing secrets in the Vault or as environment secrets, never in the script itself. Signing with a private key is slower in Safe mode than in Developer mode: roughly 1.4 seconds against 0.45 seconds for one RS256 signature on a 2048-bit key, because the arithmetic runs in JavaScript rather than in native code. Loading the library is not what costs; the signature is. Switch the request to Developer mode if that per-request cost matters more to you than running inside the sandbox, unless your organization has restricted scripts to Safe mode - see Organization resources. See Import packages into your scripts for everything require() can load, both built in and from npm.

Code Snippets

The script editor includes a built-in snippets library with ready-to-use patterns for tests, variable operations, and logging. Click Snippets in the editor toolbar to browse and insert them. View all available snippets →