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 modelled on Chai’s expect BDD API. The chain accepts these passthrough words for readability — they don’t change behavior: to, be, been, is, that, which, and, has, have, with, at, of, same, but, does, still, also.

It also accepts these modifiers that change the next assertion: .deep (structural equality), .nested (dotted/bracket property paths), .own (own properties only), .any / .all (for .keys).

MethodBehavior
.equal(v) / .equals(v) / .eq(v)Strict ===. .deep.equal(v) compares structurally.
.eql(v) / .eqls(v)Deep (structural) equality — not key-order sensitive.

.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.).
.instanceof(Ctor) / .instanceOf(Ctor)value instanceof Ctor.
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). .deep.include(v) matches members/values structurally.
.match(regex) / .matches(regex)Regex test against the value.
.string(substr)Value is a string that contains substr.
.oneOf(arr)Value is one of arr (common for pro.expect(pro.response.code).to.be.oneOf([200, 201])).
.members(arr)Same elements as arr, order-independent.
.keys(...names) / .key(name)Object has the named keys. .all.keys(...) requires all (default); .any.keys(...) requires at least one. 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.json()).to.deep.include({ created: true });
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.
.closeTo(n, delta) / .approximately(n, delta)`

.lengthOf(n) / .length(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).
.exist / .existsNot null and not undefined.
.okTruthy.
.emptyEmpty string, empty array, or empty object.
.finiteA finite number (not NaN / Infinity).
pro.expect(pro.response.cookies.has('session')).to.be.true;
pro.expect(data.token).to.exist;
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. Use .nested.property('a.b[1]') for a path, and .own.property(name) to require an own (non-inherited) property.

pro.expect(data).to.have.property('user').and.to.have.property('id', 42);
pro.expect(data).to.have.nested.property('items[0].id');
MethodBehavior
.throw([matcher]) / .throws(...)The value (a function) throws; optional matcher is a substring, regex, or error constructor.
.satisfy(fn) / .satisfies(fn)fn(value) returns truthy.
pro.expect.fail(msg)Force-fail with a message.

.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 },
},
});

Postman-style assertions that read straight off the response, so you don’t have to pull out pro.response.code yourself. Each throws on mismatch (so a pro.test block records the failure) and supports .not.

AssertionBehavior
.to.have.status(code)Status code equals code (a number), e.g. 200.
.to.have.status(name)Status reason text equals name (a string), e.g. "Created".
.to.have.header(name)Response has the header (case-insensitive).
.to.have.header(name, value)Header equals value.
.to.have.body()Body is non-empty.
.to.have.body(string | regex)Body equals the string, or matches the regex.
.to.have.jsonBody()Body parses as JSON.
.to.have.jsonBody(path)JSON body has the dotted/bracket path.
.to.have.jsonBody(path, value)JSON body at path deep-equals value.
.to.have.jsonBody(object)Whole JSON body deep-equals object.
.to.have.jsonSchema(schema)JSON body validates against schema.
.to.be.okStatus is exactly 2xx.
.to.be.successStatus is 2xx.
.to.be.info / .redirection / .clientError / .serverErrorStatus is 1xx / 3xx / 4xx / 5xx.
.to.be.errorStatus is ≥ 400.
pro.test('created', function () {
pro.response.to.have.status(201);
pro.response.to.have.header('Location');
pro.response.to.have.jsonBody('id');
pro.response.to.not.be.error;
});

pm is a full alias of pro, and Probe also ships the response-cookie / variable / info surfaces Postman scripts expect, so most collections run unchanged:

Postman APINotes
pm.test, pm.test.skip, pm.test.index().skip records a skipped test; .index() returns tests run so far.
pm.expect(...) + pm.expect.fail(...)The Chai chain documented above.
pm.response.*.code, .status, .responseTime, .responseSize, .text(), .json(), .reason(), .headers.get/has/all/each (case-insensitive), .cookies.get/has, and the .to.have.* / .to.be.* assertions above.
pm.cookies.get/has/toObjectTop-level cookie access for the response’s domain.
pm.variables.get, .set (creates a local variable), .has, .replaceIn, .toObject.
pm.environment / pm.collectionVariables / pm.globals.get, .set, .unset, .has, .clear, .toObject.
pm.iterationData.get/has/toObjectRead-only data-file row (empty outside a data-driven run).
pm.info.eventName, .iteration, .iterationCount, .requestName, .requestId.

Older collections that predate pm.* also work through these legacy globals:

Legacy globalMaps to
tests['name'] = boolEach key becomes a pass/fail test.
responseBody / responseCode.code / responseCode.name / responseTimeThe response body string / status code / reason / timing.
postman.setEnvironmentVariable / getEnvironmentVariable / clearEnvironmentVariable(s)pm.environment.set / .get / .unset / .clear.
postman.setGlobalVariable / getGlobalVariable / clearGlobalVariable(s)pm.globals.*.
postman.getResponseHeader(name)pm.response.headers.get(name).
postman.setNextRequest(name)pm.execution.setNextRequest(name).

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).