Skip to main content
Bruno provides a powerful JavaScript scripting engine that allows you to automate complex workflows, manipulate requests and responses, and integrate with external libraries. Scripts can be executed at different stages of the request lifecycle.

Script Types

Bruno supports three types of scripts:

Pre-Request

Execute before sending the request

Post-Response

Execute after receiving the response

Tests

Run assertions and validations

Pre-Request Scripts

Pre-request scripts run before Bruno sends the HTTP request. Use them to set headers, modify the request body, generate dynamic values, or perform authentication.

Basic Example

// Set custom headers
req.setHeader('X-Request-ID', Date.now().toString());
req.setHeader('Authorization', 'Bearer ' + bru.getEnvVar('token'));

// Modify request body
const body = req.getBody();
body.timestamp = new Date().toISOString();
req.setBody(body);

Authentication Example

const username = "bruno";
const password = "della";

const authString = `${username}:${password}`;
const encodedAuthString = require('btoa')(authString);

req.setHeader("Authorization", `Basic ${encodedAuthString}`);

Dynamic Request Body

// Create multipart form data programmatically
const FormData = require("form-data");
const form = new FormData();

form.append('user_id', bru.getVar('userId'));
form.append('file_name', 'document.pdf');
form.append('timestamp', new Date().toISOString());

req.setBody(form);

Post-Response Scripts

Post-response scripts execute after receiving the response. Use them to extract data, set variables for subsequent requests, or perform custom processing.

Extract Response Data

// Parse response and set variables
const data = res.getBody();

// Set runtime variables
bru.setVar('userId', data.user.id);
bru.setVar('sessionToken', data.session.token);

// Set environment variables
bru.setEnvVar('authToken', data.auth.token);

// Persist variables across collections
bru.setEnvVar('refreshToken', data.refresh_token, { persist: true });

Response Transformation

// Modify response for display
const responseData = res.getBody();

// Filter sensitive data
delete responseData.password;
delete responseData.creditCard;

// Add computed fields
responseData.fullName = `${responseData.firstName} ${responseData.lastName}`;
responseData.isActive = responseData.status === 'active';

res.setBody(responseData);

Test Scripts

Test scripts allow you to write assertions and validations using Chai assertion library.

Basic Tests

test("should return successful response", function() {
  const data = res.getBody();
  expect(res.getStatus()).to.equal(200);
  expect(data).to.have.property('success', true);
});

test("response time is acceptable", function() {
  expect(res.getResponseTime()).to.be.below(2000);
});

Advanced Assertions

test("validate user object", function() {
  const data = res.getBody();
  
  expect(data).to.have.property('user');
  expect(data.user).to.be.an('object');
  expect(data.user.email).to.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
  expect(data.user.age).to.be.a('number').and.to.be.at.least(18);
  expect(data.user.roles).to.be.an('array').that.includes('user');
});

Request and Response API

Request Object (req)

req.getUrl()              // Get full URL
req.setUrl(url)           // Set URL
req.getHost()             // Get hostname
req.getPath()             // Get path
req.getQueryString()      // Get query string
req.getHeaders()          // Get all headers
req.getHeader(name)       // Get specific header
req.setHeader(name, val)  // Set header
req.setHeaders(obj)       // Set multiple headers
req.deleteHeader(name)    // Delete header
req.deleteHeaders(arr)    // Delete multiple headers
req.getBody()             // Get parsed body
req.getBody({ raw: true })// Get raw body string
req.setBody(data)         // Set body (auto-stringifies JSON)
req.setBody(data, { raw: true }) // Set raw body
req.getMethod()           // Get HTTP method
req.setMethod(method)     // Set HTTP method
req.getName()             // Get request name
req.getPathParams()       // Get path parameters
req.getTags()             // Get request tags
req.setTimeout(ms)        // Set timeout
req.setMaxRedirects(num)  // Set max redirects

Response Object (res)

res.getStatus()           // Get status code
res.getStatusText()       // Get status text
res.getResponseTime()     // Get response time in ms
res.getHeaders()          // Get all headers
res.getHeader(name)       // Get specific header
res.getBody()             // Get parsed response body
res.setBody(data)         // Modify response body
res.getDataBuffer()       // Get raw buffer
res.getSize()             // Get size { header, body, total }
// Shorthand property access
res.status                // Same as res.getStatus()
res.headers               // Same as res.getHeaders()
res.body                  // Same as res.getBody()

// Query response data directly
res('user.email')         // Get nested property
res('items[0].name')      // Array access

Built-in Libraries

Bruno includes several libraries for common tasks:

crypto-js

Encryption and hashing
const CryptoJS = require('crypto-js');
const hash = CryptoJS.SHA256('message');
const encrypted = CryptoJS.AES.encrypt('data', 'key');

axios

HTTP client for making requests
const axios = require('axios');
const response = await axios.get('https://api.example.com');

uuid

Generate unique identifiers
const { v4: uuidv4 } = require('uuid');
const id = uuidv4();

cheerio

Parse and query HTML
const cheerio = require('cheerio');
const $ = cheerio.load(res.getBody());
const title = $('title').text();

jsonwebtoken

Work with JWT tokens
const jwt = require('jsonwebtoken');
const decoded = jwt.decode(token);

xml2js

Parse XML responses
const xml2js = require('xml2js');
const parser = new xml2js.Parser();
const result = await parser.parseStringPromise(xmlString);
All built-in libraries are available without installation. Just require() them in your scripts.

Advanced Patterns

Chaining Requests

// Make additional requests within scripts
await test("create and verify user", async () => {
  // Create user
  const createRes = await bru.sendRequest({
    url: 'https://api.example.com/users',
    method: 'POST',
    data: { name: 'John Doe', email: '[email protected]' }
  });
  
  const userId = createRes.data.id;
  bru.setVar('newUserId', userId);
  
  // Verify user was created
  const verifyRes = await bru.sendRequest({
    url: `https://api.example.com/users/${userId}`,
    method: 'GET'
  });
  
  expect(verifyRes.data.name).to.equal('John Doe');
});

Error Handling

try {
  const response = await bru.sendRequest({
    url: 'https://api.example.com/data',
    method: 'GET'
  });
  
  bru.setVar('data', response.data);
} catch (error) {
  console.error('Request failed:', error.message);
  
  // Handle specific error cases
  if (error.status === 404) {
    bru.setVar('dataNotFound', true);
  } else {
    throw error; // Re-throw unexpected errors
  }
}

Custom Utilities

// Create reusable utility functions
function generateRequestId() {
  const { v4: uuidv4 } = require('uuid');
  return `req_${uuidv4()}`;
}

function signRequest(method, path, body) {
  const CryptoJS = require('crypto-js');
  const secret = bru.getEnvVar('apiSecret');
  const timestamp = Date.now();
  const payload = `${method}${path}${timestamp}${JSON.stringify(body)}`;
  return CryptoJS.HmacSHA256(payload, secret).toString();
}

// Use utilities
const requestId = generateRequestId();
const signature = signRequest('POST', '/api/data', req.getBody());

req.setHeader('X-Request-ID', requestId);
req.setHeader('X-Signature', signature);
Scripts run in a sandboxed environment. Use Developer Mode for full Node.js access.

Best Practices

Each script should have a single, clear purpose. Separate setup, execution, and validation logic.
// Good
test("should return user profile with email and name", function() { ... });

// Bad
test("test1", function() { ... });
Always use await with async operations and wrap tests with await test():
await test("async test", async () => {
  const result = await someAsyncOperation();
  expect(result).to.be.ok;
});
Clear sensitive data and temporary variables after use:
// After tests complete
bru.deleteVar('tempToken');
bru.deleteVar('sessionId');

Variables

Learn about variable scopes and management

Assertions

Master test assertions and operators

Workflows

Build complex multi-request workflows

Environments

Manage environment variables

Build docs developers (and LLMs) love