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

# Masking

> Mask sensitive data with the Apitally SDK for JavaScript.

The Apitally SDK provides mechanisms for masking sensitive data in captured requests, responses, and application logs.

## Default masking

The SDK automatically masks common sensitive query parameters, headers, and request/response body fields based on built-in patterns. For example, fields named `password`, `token`, `secret`, or headers like `Authorization` are masked by default.

See the [data privacy](/data-privacy#data-masking) page for more information about default masking.

## Custom masking

You can extend the default masking rules by providing additional regular expressions via the `maskQueryParams`, `maskHeaders`, and `maskBodyFields` options. Patterns match anywhere within the name. Use `^` and `$` anchors for exact matches, and the `i` flag for case-insensitive matching.

Body field patterns recursively match keys in JSON objects and replace the corresponding values only when they are strings.

The following example uses Hono. The same masking options are available for all supported frameworks.

```javascript Hono example {12-15} theme={null}
import { Hono } from "hono";
import { useApitally } from "apitally";

const app = new Hono();

useApitally(app, {
  writeToken: "your-write-token",
  env: "dev",
  captureRequestHeaders: true,
  captureRequestBody: true,
  captureResponseBody: true,
  // Mask specific query parameters, headers and body fields
  maskQueryParams: [/^card_number$/i, /^account_id$/i],
  maskHeaders: [/^X-Custom-Key$/i, /^X-Internal-/i],
  maskBodyFields: [/^credit_card$/i, /social_security/i],
});
```

### Body masking callbacks

For more control over body masking, you can provide callback functions via the `maskRequestBody` and `maskResponseBody` options. Each function receives the captured body as a `Buffer` and the ended request [`ReadableSpan`](https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_sdk-trace-base.ReadableSpan.html). Request metadata is available through [`span.attributes`](/sdk-reference/javascript/v1/attributes). Each function should return the masked body as a `Buffer`, or `null` to mask the entire body.

```javascript Callback function examples {49-51} theme={null}
import { Hono } from "hono";
import { useApitally } from "apitally";

function maskRequestBody(body, span) {
  const path = span.attributes["url.path"];
  // Mask entire request body for admin endpoints
  if (typeof path === "string" && path.startsWith("/admin/")) {
    return null;
  }
  // Otherwise, return the original request body
  return body;
}

function maskResponseBody(body, span) {
  const path = span.attributes["url.path"];
  // Mask entire response body for admin endpoints
  if (typeof path === "string" && path.startsWith("/admin/")) {
    return null;
  }
  // Mask specific fields in user profile responses
  if (typeof path === "string" && path.startsWith("/users/")) {
    try {
      const data = JSON.parse(body.toString());
      if (typeof data === "object" && data !== null && !Array.isArray(data)) {
        if ("email" in data) {
          data.email = "******";
        }
        if ("phone" in data) {
          data.phone = "******";
        }
        return Buffer.from(JSON.stringify(data));
      }
    } catch {
      // Return the original body if parsing fails
    }
  }
  // Otherwise, return the original response body
  return body;
}

const app = new Hono();

useApitally(app, {
  writeToken: "your-write-token",
  env: "dev",
  captureRequestHeaders: true,
  captureRequestBody: true,
  captureResponseBody: true,
  // Mask request and response bodies using custom logic
  maskRequestBody,
  maskResponseBody,
});
```

<Note>
  Callbacks are applied before pattern-based field masking. If the returned body contains JSON, it is still masked using the default and custom `maskBodyFields` patterns.
</Note>

### Log record masking callback

To mask sensitive data in application logs, provide a callback function via the `maskLogRecord` option. The function receives an OpenTelemetry [`ReadWriteLogRecord`](https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_sdk-logs.ReadWriteLogRecord.html). You can modify the log message with `record.setBody()` and structured fields with `record.setAttribute()`. Return the same record to keep it, or `null` or `undefined` to drop it.

```javascript Callback function example {21} theme={null}
import { Hono } from "hono";
import { useApitally } from "apitally";

function maskLogRecord(record) {
  // Drop logs from console
  if (record.instrumentationScope.name === "console") {
    return null;
  }
  // Mask tokens
  if (typeof record.body === "string") {
    record.setBody(record.body.replace(/token=\S+/g, "token=******"));
  }
  return record;
}

const app = new Hono();

useApitally(app, {
  writeToken: "your-write-token",
  env: "dev",
  maskLogRecord,
});
```
