Skip to content

Scripting API Reference

The pro global is the only entry point a script needs. Everything you can read or change lives under it. This page documents every method exposed by Probe’s QuickJS runtime, grouped by namespace.

For the high-level picture — when scripts run, how to create a rule, sandbox limits — see the Scripting Overview.

gmp and pm are aliases of pro. Anywhere you see pro.foo below, gmp.foo and pm.foo work identically.

The outgoing request. Mutable in request scripts, read-only in response scripts (assignments warn and are ignored). All mutations are sent upstream.

Get or set the HTTP method.

pro.request.method; // "GET"
pro.request.method = 'POST'; // overrides the method

Get or set the full URL string.

pro.request.url;
pro.request.url = 'https://staging.example.com/api/v2/users';

A header collection with these methods:

MethodBehavior
add({key, value})Set a header. Equivalent to upsert.
upsert({key, value})Set a header, replacing any existing entry with the same name.
remove(key)Delete a header by name.
get(key)Return the header value, or undefined.
has(key)Return true if the header is present.
toObject()Snapshot of all headers as a plain object.
pro.request.headers.upsert({ key: 'Authorization', value: 'Bearer ' + token });
pro.request.headers.remove('Cookie');
if (!pro.request.headers.has('User-Agent')) {
pro.request.headers.add({ key: 'User-Agent', value: 'probe-script/1.0' });
}

Get or set the request body as a raw string. For JSON bodies, you handle JSON.stringify yourself.

pro.request.body.raw; // current body string
pro.request.body.raw = JSON.stringify({ a: 1 }); // replace the body

Available in response scripts only. Read-only — you can inspect the response and assert on it, but you can’t rewrite it from a script. Use Map Local or Breakpoints for that.

HTTP status code as a number.

pro.expect(pro.response.code).to.equal(200);

Status text — "OK", "Not Found", etc.

Server response time in milliseconds.

pro.expect(pro.response.responseTime).to.be.below(500);

Response body size in bytes.

The raw response body as a string.

console.log(pro.response.body);

Returns the body as a string. Equivalent to pro.response.body, kept for Postman parity.

Parses the body as JSON. Throws if the body isn’t valid JSON.

const data = pro.response.json();
console.log(data.userId);

Same shape as request headers, but read-only:

MethodBehavior
get(key)Header value or undefined.
has(key)true if the header is present.
toObject()All headers as a plain object.
const ct = pro.response.headers.get('Content-Type');
pro.expect(ct).to.contain('application/json');

Cookies parsed from Set-Cookie headers, with the same get / has / toObject interface.

if (pro.response.cookies.has('session')) {
pro.variables.replaceIn(pro.response.cookies.get('session'));
}

A read-only merged view across all variable scopes. Precedence is collection > environment > globals. To set a variable, use one of the scoped objects (pro.environment, pro.globals, pro.collectionVariables).

Returns the value, or undefined if the key is unknown in every scope.

const baseUrl = pro.variables.get('baseUrl');

Returns true if any scope has the key.

Returns the merged map (collection wins on conflict).

Resolves {{var}} placeholders in a string using the same precedence. Also resolves dynamic variables prefixed with $.

const url = pro.variables.replaceIn('{{baseUrl}}/users/{{userId}}');

pro.environment / pro.globals / pro.collectionVariables

Section titled “pro.environment / pro.globals / pro.collectionVariables”

Three scoped variable stores. Each exposes the same methods. Mutations are reported back to Probe and persisted to the active environment.

MethodBehavior
get(key)Read a value.
set(key, value)Write a value. Coerced to string.
unset(key)Delete a value.
has(key)Test for presence.
toObject()Snapshot of the scope.
clear()Remove every key in this scope.
name (getter)The scope name — "environment", "globals", or "collection".
// Capture a token from a login response and stash it for later requests.
pro.environment.set('authToken', pro.response.json().token);
// Wipe a stale value.
pro.globals.unset('deviceId');

Native Rust implementations exposed as JS functions — fast and deterministic.

SHA-256 hex digest.

pro.crypto.sha256('hello');
// "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

SHA-1 hex digest.

MD5 hex digest.

HMAC-SHA256 hex digest.

const sig = pro.crypto.hmacSha256(timestamp + body, secret);
pro.request.headers.upsert({ key: 'X-Signature', value: sig });

HMAC-SHA1 hex digest.

Standard Base64 encode.

pro.crypto.base64Encode('Hello'); // "SGVsbG8="

Standard Base64 decode. Returns a string starting with Error: on bad input.

Percent-encode for URLs.

pro.crypto.urlEncode('hello world&foo=bar');
// "hello%20world%26foo%3Dbar"

Percent-decode. Returns a string starting with Error: on bad input.

Decode a JWT — splits on ., base64-decodes the header and payload, and returns a parsed object:

{
header: { alg: 'HS256', typ: 'JWT' },
payload: { sub: '1234567890', name: 'John' },
signature: 'abc123...'
}
const auth = pro.request.headers.get('Authorization') || '';
const token = auth.replace(/^Bearer\s+/, '');
const decoded = pro.crypto.jwtDecode(token);
console.log('exp:', decoded.payload.exp);

The function does not verify the signature.

The assertion library, modelled on Chai’s BDD chain. pro.test wraps a block of assertions so one failure doesn’t kill the whole script and so each block shows up in the scripting console with pass/fail status.

Run fn and record the outcome under name. Throws inside fn are caught and turned into failures.

pro.test('status is 200', function () {
pro.expect(pro.response.code).to.equal(200);
});

Returns an assertion chain. The chain accepts the following passthrough words for readability — they don’t change behavior: to, be, been, is, that, which, and, has, have, with, at, of, same.

MethodBehavior
.equal(v) / .equals(v) / .eq(v)Strict ===.
.eql(v) / .eqls(v) / .deep.equal(v)Deep equality (via JSON round-trip).

.not flips the next assertion. Apply it anywhere in the chain.

pro.expect(200).to.not.equal(404);
MethodBehavior
.a(type) / .an(type)Check typeof ('string', 'number', 'object', 'array', 'null', 'undefined', etc.).
.string / .numberShortcuts for .a('string') / .a('number').
pro.expect('hello').to.be.a('string');
pro.expect([1, 2, 3]).to.be.an('array');
MethodBehavior
.include(v) / .includes(v) / .contain(v) / .contains(v)Substring (string), element (array), or subset of keys/values (object).
.match(regex)Regex test against the value.
.oneOf(arr)Value is one of arr.
.members(arr)Same elements as arr, order-independent.
.keys(...names)Object has every named key. Accepts an array or a vararg list.
pro.expect('hello world').to.include('world');
pro.expect([1, 2, 3]).to.include(2);
pro.expect({ id: 1, name: 'Ada' }).to.include({ name: 'Ada' });
pro.expect(pro.response.headers.get('Content-Type')).to.match(/json/);
MethodBehavior
.above(n) / .greaterThan(n) / .gt(n)value > n.
.below(n) / .lessThan(n) / .lt(n)value < n.
.least(n) / .gte(n)value >= n.
.most(n) / .lte(n)value <= n.
.within(min, max)min <= value <= max.

.lengthOf(n) — checks value.length === n.

pro.expect(pro.response.json().items).to.have.lengthOf(10);

These trigger on access — no parentheses.

GetterBehavior
.trueStrict === true.
.falseStrict === false.
.null=== null.
.undefined=== undefined.
.NaNNumber.isNaN(value).
.okTruthy.
.emptyEmpty string, empty array, or empty object.
pro.expect(pro.response.cookies.has('session')).to.be.true;
pro.expect(data.error).to.be.null;

.property(name) walks into a property — and optionally asserts its value. After this call, the chain’s value becomes that property.

pro.expect(data).to.have.property('user').and.to.have.property('id', 42);

.jsonSchema(schema) — validates against a small JSON Schema subset: type (object, array, string, number, integer, boolean), enum, minimum, maximum, minLength, maxLength, required (array of names), and nested properties.

pro.expect(pro.response.json()).to.have.jsonSchema({
type: 'object',
required: ['userId', 'name'],
properties: {
userId: { type: 'integer' },
name: { type: 'string', minLength: 1 },
},
});

Same console you’d use anywhere. Output goes to Probe’s scripting console.

MethodBehavior
console.log(...args) / console.info(...)Info-level message. Args are stringified; objects use JSON.stringify.
console.warn(...)Warning-level message.
console.error(...)Error-level message.
console.debug(...)Debug-level message.
console.table(value)Pretty-prints value as JSON.
console.time(label) / console.timeEnd(label)Wall-clock timer. timeEnd logs <label>: <ms>ms.
console.clear()Empty the captured log buffer for this run.

Make a blocking HTTP request from inside a script. Capped at 5 sub-requests per execution with a 10 second per-request timeout. Self-signed certificates are accepted.

urlOrOptions is either a URL string (defaults to GET) or an options object:

FieldTypeDefault
urlstringrequired
methodstring'GET'
headersobject{}
bodystring''

Returns a response object synchronously:

FieldType
codenumber — HTTP status, 0 on transport error
statusstring — reason phrase, or "Error: ..." on failure
headersobject
bodystring
responseTimenumber — milliseconds
text()function — returns body
json()function — parses body

If a callback(err, response) is provided, it’s also invoked. err is always null — transport errors arrive as code: 0.

const res = pro.sendRequest({
url: 'https://api.example.com/auth/refresh',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refreshToken: pro.environment.get('refreshToken') }),
});
if (res.code === 200) {
pro.environment.set('authToken', res.json().token);
}

Used inside a collection runner — has no effect on standalone live-traffic scripts.

Tell the runner to jump to the request named name after this one finishes.

Skip the current request entirely. The script still finishes; the network call doesn’t happen.

Read-only metadata about the current execution.

PropertyType
pro.info.requestNamestring — display name of the request being scripted.
pro.info.requestIdstring — internal ID.

A handful of {{...}} placeholders resolve to a fresh value every time. Use them inside pro.variables.replaceIn(...), in Composer fields, or in scripted strings.

PlaceholderProduces
{{$guid}}A v4 UUID (e.g. 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed).
{{$timestamp}}Unix timestamp in seconds.
{{$isoTimestamp}}ISO 8601 UTC timestamp like 2026-05-08T13:24:31.412Z.
{{$randomInt}}Random integer in [0, 1000).
{{$randomEmail}}userN@example.com with a random integer.
const url = pro.variables.replaceIn('https://api.example.com/orders?nonce={{$guid}}&t={{$timestamp}}');
LimitValue
Wall-clock timeout per script10 seconds
Memory cap64 MB
Stack size1 MB
pro.sendRequest calls per script5
pro.sendRequest per-request timeout10 seconds

No require, import, fetch, XMLHttpRequest, process, Buffer, fs, DOM, or timers (setTimeout/setInterval).