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

# Scripting

> JavaScript hooks to modify requests and responses on the fly

httpmon lets you write JavaScript scripts that intercept and modify HTTP traffic in real time. You can add headers, block requests, mock responses, set breakpoints, and more.

Scripts live in `~/.httpmon/scripts/`. Each script is a `.js` file with YAML frontmatter in comments followed by JavaScript hook functions.

## Script format

A script has two parts: a YAML frontmatter block (wrapped in `// ---` comment delimiters) and one or both hook functions.

```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
// ---
// name: My Script
// match:
//   - "*://example.com/*"
// enabled: true
// ---

function onRequest(ctx) {
  // Runs before the request is sent upstream
}

function onResponse(ctx) {
  // Runs before the response reaches the client
}
```

### Frontmatter fields

| Field     | Required | Description                                       |
| --------- | -------- | ------------------------------------------------- |
| `name`    | Yes      | Display name shown in the script manager          |
| `match`   | Yes      | URL patterns to match. Supports `*` wildcards.    |
| `enabled` | No       | `true` or `false`. Defaults to `true` if omitted. |

### Hooks

**`onRequest(ctx)`** runs before the request is sent to the server.

| Field                | Type     | Description                                            |
| -------------------- | -------- | ------------------------------------------------------ |
| `ctx.method`         | string   | HTTP method (read/write)                               |
| `ctx.url`            | string   | Full URL (read/write)                                  |
| `ctx.headers`        | object   | Request headers (read/write)                           |
| `ctx.body`           | string   | Request body (read/write)                              |
| `ctx.blocked`        | bool     | Set to `true` to block the request                     |
| `ctx.respondWith()`  | function | Return a synthetic response without hitting the server |
| `ctx.breakpoint()`   | function | Pause the request and open an interactive editor       |
| `ctx.readFile(path)` | function | Read a file relative to the script directory           |

**`onResponse(ctx)`** runs before the response reaches the client.

| Field                | Type     | Description                                  |
| -------------------- | -------- | -------------------------------------------- |
| `ctx.status`         | int      | Status code (read/write)                     |
| `ctx.headers`        | object   | Response headers (read/write)                |
| `ctx.body`           | string   | Response body (read/write)                   |
| `ctx.respondWith()`  | function | Replace the response entirely                |
| `ctx.breakpoint()`   | function | Pause the response for interactive editing   |
| `ctx.readFile(path)` | function | Read a file relative to the script directory |

## Script manager

Press **S** in the TUI to open the script manager. From there you can toggle, create, and delete scripts.

| Key       | Action                                                                        |
| --------- | ----------------------------------------------------------------------------- |
| **Space** | Toggle a script on or off                                                     |
| **n**     | Create a new script from a template (opens in `$EDITOR`)                      |
| **e**     | Edit selected script in `$EDITOR`                                             |
| **m**     | Quick-add a [Map Local](/features/map-local) rule (pattern + local file path) |
| **d**     | Delete a script (with confirmation)                                           |

Scripts are reloaded each time the manager opens. Scripts are tagged with category badges — **Script**, **Map Local**, or **Breakpoint** — based on which APIs they use (`ctx.respondWith()` for Map Local, `ctx.breakpoint()` for Breakpoint).

<Frame>
  <img src="https://mintcdn.com/pragmaticoslu/GKMvH6x25ZdEJHbo/images/screenshots/scripting.png?fit=max&auto=format&n=GKMvH6x25ZdEJHbo&q=85&s=3d7e9762c3b5cd60110c0465ab5539d7" alt="httpmon script manager" width="5877" height="1904" data-path="images/screenshots/scripting.png" />
</Frame>

## Examples

All examples below use [httpbin.org](https://httpbin.org) so you can test them immediately.

<AccordionGroup>
  <Accordion title="Modify request headers">
    Add custom headers to outgoing requests. The httpbin `/headers` endpoint echoes back all received headers, so you can verify the script works.

    ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // ---
    // name: Add Custom Header
    // match:
    //   - "*://httpbin.org/headers"
    // enabled: true
    // ---

    function onRequest(ctx) {
      ctx.headers["X-Custom-Header"] = "httpmon-test";
      ctx.headers["X-Request-ID"] = "12345";
    }
    ```
  </Accordion>

  <Accordion title="Modify response headers">
    Override the status code or headers on a response before it reaches the client.

    ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // ---
    // name: Override Response
    // match:
    //   - "*://httpbin.org/json"
    // enabled: true
    // ---

    function onResponse(ctx) {
      ctx.status = 200;
      ctx.headers["X-Modified"] = "true";
    }
    ```
  </Accordion>

  <Accordion title="Block requests">
    Block all requests to slow endpoints. Blocked requests never leave the proxy.

    ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // ---
    // name: Block Slow Endpoints
    // match:
    //   - "*://httpbin.org/delay/*"
    // enabled: true
    // ---

    function onRequest(ctx) {
      ctx.blocked = true;
    }
    ```
  </Accordion>

  <Accordion title="Mock a response">
    Return a synthetic JSON response without hitting the server. Use `ctx.respondWith()` to define the status, body, and headers.

    ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // ---
    // name: Mock GET Response
    // match:
    //   - "*://httpbin.org/get"
    // enabled: true
    // ---

    function onRequest(ctx) {
      ctx.respondWith({
        status: 200,
        body: JSON.stringify({ mocked: true, tool: "httpmon" }),
        headers: { "Content-Type": "application/json" }
      });
    }
    ```
  </Accordion>

  <Accordion title="Serve a local file">
    Serve a file from disk instead of forwarding the request. The `file` path is relative to the script directory (`~/.httpmon/scripts/`).

    ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // ---
    // name: Serve Local Config
    // match:
    //   - "*://httpbin.org/get"
    // enabled: true
    // ---

    function onRequest(ctx) {
      ctx.respondWith({
        status: 200,
        file: "mock-response.json"
      });
    }
    ```
  </Accordion>

  <Accordion title="Set a breakpoint">
    Pause the request flow and open an interactive editor. You can inspect and modify the request before it is sent to the server.

    ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // ---
    // name: Inspect POST Requests
    // match:
    //   - "*://httpbin.org/post"
    // enabled: true
    // ---

    function onRequest(ctx) {
      ctx.breakpoint();
    }
    ```
  </Accordion>

  <Accordion title="Add an auth header">
    Inject a bearer token into requests. The httpbin `/bearer` endpoint validates the `Authorization` header and returns 200 on success or 401 without it.

    ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // ---
    // name: Inject Bearer Token
    // match:
    //   - "*://httpbin.org/bearer"
    // enabled: true
    // ---

    function onRequest(ctx) {
      ctx.headers["Authorization"] = "Bearer my-secret-token";
    }
    ```
  </Accordion>

  <Accordion title="Redirect requests">
    Rewrite the URL to redirect a request to a different endpoint. The client sees the response from the new URL.

    ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // ---
    // name: Redirect to IP Endpoint
    // match:
    //   - "*://httpbin.org/get"
    // enabled: true
    // ---

    function onRequest(ctx) {
      ctx.url = "https://httpbin.org/ip";
    }
    ```
  </Accordion>
</AccordionGroup>

## URL matching

The `match` field accepts an array of glob patterns. Use `*` as a wildcard for any sequence of characters.

| Pattern                   | Matches                             |
| ------------------------- | ----------------------------------- |
| `*://httpbin.org/*`       | Any scheme, any path on httpbin.org |
| `*://httpbin.org/get`     | Only the `/get` endpoint            |
| `*://httpbin.org/delay/*` | Any delay duration                  |
| `*://*.example.com/*`     | Any subdomain of example.com        |

You can specify multiple patterns to match different endpoints with a single script:

```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}}
match:
  - "*://api.example.com/v1/*"
  - "*://api.example.com/v2/*"
```

## Error handling

If a script throws an error, httpmon catches it and continues processing the request normally. The error is tracked and displayed in the script manager next to the script name, so you can spot and fix issues without disrupting traffic.

***

See the [Script API reference](/reference/script-api) for the full list of context fields and methods.
