Docs Traffic Recorder

Traffic Recorder

The Traffic Recorder captures live HTTP/HTTPS traffic flowing through Mockarty and turns it into mocks, test collections, and performance scripts. It acts as an intercepting proxy between your application and the real upstream service, recording every request/response pair in real time.

Why Record Traffic?

  • Auto-generate mocks from production traffic. Point your staging environment at the recorder, run your test suite, and export the captured traffic as Mockarty mocks. No manual JSON authoring.
  • Debug API integration issues. See the exact bytes your application sends and receives, including headers, timing breakdowns (DNS, TLS handshake, TTFB), and compressed vs. decompressed bodies.
  • Regression testing. Record a known-good session, export it as a test collection, and replay it on every CI build to catch contract changes.
  • Compliance auditing. Keep a timestamped log of all API calls between your services during a compliance window.
  • Chaos engineering. Inject latency, jitter, errors, and bandwidth throttling to see how your application handles degraded networks — without touching the upstream service.

Recording Modes

Reverse Proxy

Your application talks to Mockarty (e.g. http://localhost:8085), and Mockarty forwards every request to the real upstream server (e.g. https://api.stripe.com).

App  ──►  Mockarty :8085  ──►  api.stripe.com
                 │
          (records traffic)

Best for: targeting a single upstream service, local development, CI pipelines.

Forward Proxy

Mockarty acts as a classic HTTP proxy. Configure your application (or OS) to use HTTP_PROXY=http://localhost:8085 and all outbound traffic flows through the recorder.

App  ──HTTP_PROXY──►  Mockarty :8085  ──►  any upstream
                            │
                     (records traffic)

HTTP requests are fully captured. HTTPS traffic is tunneled via the CONNECT method. To decrypt HTTPS, enable MITM interception.


Starting a Recording Session

Via the UI

  1. Navigate to Recorder in the sidebar (/ui/recorder).
  2. Click New Session.
  3. Choose a mode (Reverse Proxy or Forward Proxy).
  4. For reverse proxy, enter the Target URL (e.g. https://api.example.com).
  5. Optionally set the Listen Port (auto-assigned from 8081–8999 if left blank).
  6. Configure filters, toxics, modifications, MITM, and Map Local as needed.
  7. Click Start.

The session begins recording immediately. New entries stream into the UI via WebSocket.

Via the API

curl -X POST http://localhost:5770/ui/api/recorder/start \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "Stripe Integration Test",
    "mode": "reverse",
    "targetUrl": "https://api.stripe.com",
    "listenPort": 8085,
    "namespace": "default",
    "filters": {
      "includePaths": ["/v1/*"],
      "excludePaths": ["/v1/health"]
    },
    "toxics": {
      "delayMs": 100,
      "delayJitter": 50
    }
  }'

Response:

{
  "session": {
    "id": "a1b2c3d4-...",
    "name": "Stripe Integration Test",
    "mode": "reverse",
    "targetUrl": "https://api.stripe.com",
    "listenPort": 8085,
    "status": "running",
    "entryCount": 0,
    "createdAt": "2026-03-14T10:00:00Z",
    "expiresAt": "2026-03-14T14:00:00Z"
  }
}

Session Configuration Options

Field Type Description
name string Human-readable label. Auto-generated if empty.
mode "reverse" or "forward" Proxy mode. Default: "reverse".
targetUrl string Upstream URL. Required for reverse proxy.
listenPort int Port the proxy listens on. Auto-assigned (8081–8999) if 0.
namespace string Mockarty namespace. Default: "default".
toxics object Toxicity rules (delay, jitter, errors, bandwidth).
filters object Scope filters (hosts, paths, methods, status codes).
modifications object Request/response modification rules.
mitm object MITM TLS interception config.
mapLocal object Auto-responder using Mockarty mocks.

Scope Filters

Filters control which requests are recorded. An empty filter dimension means “allow all”. All pattern strings support glob syntax.

{
  "filters": {
    "includeHosts": ["api.example.com", "*.internal.corp"],
    "excludeHosts": ["telemetry.example.com"],
    "includePaths": ["/api/*", "/v2/*"],
    "excludePaths": ["/api/healthcheck", "/api/metrics"],
    "includeMethods": ["GET", "POST", "PUT"],
    "excludeStatus": [304, 204]
  }
}

How Filters Are Evaluated

  1. If includeHosts is non-empty, the request host must match at least one pattern.
  2. If the host matches any excludeHosts pattern, the request is skipped.
  3. Same logic for includePaths / excludePaths.
  4. If includeMethods is non-empty, the HTTP method must be in the list.
  5. If the response status code is in excludeStatus, the entry is discarded.

Glob Pattern Examples

Pattern Matches
*.example.com api.example.com, auth.example.com
/api/v1/* /api/v1/users, /api/v1/orders
/api/*/details /api/users/details, /api/orders/details

Toxicity Simulation

Inject artificial degradation into proxied traffic to test how your application handles real-world network conditions.

{
  "toxics": {
    "delayMs": 200,
    "delayJitter": 100,
    "errorRate": 0.05,
    "bandwidthKBps": 50
  }
}
Field Type Description
delayMs int Fixed latency (ms) added before each response.
delayJitter int Random jitter in the range +-jitter ms, added on top of delayMs.
errorRate float Fraction of requests to fail with HTTP 503 (0.0 to 1.0).
bandwidthKBps int Limit response throughput in KB/s. 0 = unlimited.

Example scenarios:

  • Simulate a slow third-party API: delayMs: 500, delayJitter: 200
  • Test circuit breaker activation: errorRate: 0.3
  • Simulate mobile network conditions: bandwidthKBps: 25, delayMs: 150

Modification Rules

Modify requests and responses as they pass through the proxy. Rules are applied in order. Changes affect what gets sent upstream and what your application receives, but the original request is still captured in the entry.

Header Modifications

{
  "modifications": {
    "requestHeaders": [
      { "action": "add", "name": "X-Debug", "value": "recorder" },
      { "action": "replace", "name": "Authorization", "value": "Bearer test-token" },
      { "action": "remove", "name": "X-Internal-ID" }
    ],
    "responseHeaders": [
      { "action": "add", "name": "X-Recorded", "value": "true" }
    ]
  }
}

Header rule actions: add, replace, remove.

URL Rewrites

Regex-based URL rewriting with capture group support:

{
  "modifications": {
    "urlRewrites": [
      {
        "match": "/api/v1/(.*)",
        "replace": "/api/v2/$1"
      }
    ]
  }
}

Body Replacements

Replace text in response bodies using plain strings or regex:

{
  "modifications": {
    "bodyReplacements": [
      {
        "match": "production-db.internal",
        "replace": "localhost:5432",
        "isRegex": false
      },
      {
        "match": "\"apiKey\":\\s*\"[^\"]+\"",
        "replace": "\"apiKey\": \"REDACTED\"",
        "isRegex": true
      }
    ]
  }
}

Updating Modifications on a Running Session

You can update modification rules without restarting the session:

curl -X PUT http://localhost:5770/ui/api/recorder/<session-id>/modifications \
  -H "Content-Type: application/json" \
  -d '{
    "modifications": {
      "requestHeaders": [
        { "action": "add", "name": "X-Trace", "value": "123" }
      ]
    }
  }'

Map Local (Auto-Responder)

When Map Local is enabled, the proxy checks whether a matching Mockarty mock exists before forwarding to the upstream. If a mock matches, its response is served locally without any network call. The entry is flagged with "mapLocal": true.

{
  "mapLocal": {
    "enabled": true,
    "namespace": "staging"
  }
}

Use cases:

  • Stub out a flaky upstream endpoint during recording.
  • Inject specific error responses for edge-case testing.
  • Combine real traffic with mocked endpoints in a single session.

SSL/TLS Interception (MITM)

In forward proxy mode, HTTPS traffic is tunneled via CONNECT and encrypted end-to-end by default. To decrypt and record HTTPS request/response bodies, enable MITM interception.

How It Works

  1. Mockarty generates a self-signed CA certificate (ECDSA P-256, 10-year validity).
  2. When a CONNECT tunnel is established, Mockarty generates a leaf certificate for the target hostname, signed by the CA.
  3. Your application (or browser) performs the TLS handshake with Mockarty’s leaf certificate.
  4. Mockarty opens a separate TLS connection to the real server.
  5. Decrypted HTTP traffic is recorded, then re-encrypted and forwarded.

Setup

Step 1: Generate the CA

curl -X POST http://localhost:5770/ui/api/recorder/ca/generate

Step 2: Download and trust the CA certificate

curl -o mockarty-ca.pem http://localhost:5770/ui/api/recorder/ca/download

Install the certificate in your OS or browser trust store:

  • macOS: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain mockarty-ca.pem
  • Linux (Ubuntu/Debian): Copy to /usr/local/share/ca-certificates/mockarty-ca.crt and run sudo update-ca-certificates
  • Windows: Double-click the .pem file and install to “Trusted Root Certification Authorities”
  • Node.js: Set NODE_EXTRA_CA_CERTS=mockarty-ca.pem
  • Go: Set SSL_CERT_FILE=mockarty-ca.pem

Step 3: Enable MITM when starting a session

curl -X POST http://localhost:5770/ui/api/recorder/start \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "forward",
    "mitm": { "enabled": true },
    "listenPort": 8085
  }'

Step 4: Configure your application

export HTTP_PROXY=http://localhost:8085
export HTTPS_PROXY=http://localhost:8085

All HTTPS traffic will now be decrypted, recorded, and re-encrypted transparently.


Exporting Recorded Traffic

HAR File

Export the session (or selected entries) as a HAR file, compatible with Chrome DevTools, Charles Proxy, and other tools.

curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/export \
  -H "Content-Type: application/json" \
  -d '{ "entryIds": [] }' \
  -o recording.har

Pass specific entryIds to export a subset, or an empty array for all entries.

Mock Generation

Convert recorded entries directly into Mockarty mocks:

curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/mocks \
  -H "Content-Type: application/json" \
  -d '{
    "entryIds": [],
    "namespace": "default",
    "prefix": "rec-",
    "tags": ["recorded", "payment-api"],
    "priority": 5
  }'

Options:

Field Description
entryIds Entries to convert. Empty = all.
namespace Target namespace for created mocks.
prefix ID prefix for generated mocks (e.g. rec-).
tags Tags applied to every generated mock.
chainId Optional chain ID for linking mocks into a workflow.
forceUpdate Overwrite existing mocks with the same ID.
priority Default priority for generated mocks.

Test Collection

Export entries as an API Tester collection for replay testing:

curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/export-collection \
  -H "Content-Type: application/json" \
  -d '{
    "collectionName": "Payment Flow Regression",
    "namespace": "default",
    "protocol": "http"
  }'

Set protocol to "tests" to generate a test script with assertions, or "performance" to generate a performance load script.

Performance Script

Export as a standalone JavaScript performance script:

curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/export-perf \
  -H "Content-Type: application/json" \
  -d '{ "entryIds": [] }' \
  -o perf-script.js

Test Script

Export as a JavaScript test script with assertions:

curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/export-test \
  -H "Content-Type: application/json" \
  -d '{ "entryIds": [] }' \
  -o test-script.js

Session Management

Limits

Limit Value
Max concurrent sessions (global) 30
Max sessions per user 2
Max entries per session 1,000 (FIFO eviction)
Session auto-expiry 4 hours
Entry retention after stop 5 days
Listen port range (auto-assign) 8081–8999
Saved configs per user 10

When a session reaches 1,000 entries, the oldest entry is evicted automatically. WebSocket subscribers receive an eviction notification so the UI stays in sync.

Session Lifecycle

  1. Running — proxy is active, entries are being captured.
  2. Stopped — proxy is shut down, entries remain accessible for export.
  3. Expired — session auto-stopped after 4 hours. Entries are retained for 5 days.

Saved Configurations

Save frequently used session configs for quick reuse:

# Save a config
curl -X POST http://localhost:5770/ui/api/recorder/configs \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Stripe Dev",
    "mode": "reverse",
    "targetUrl": "https://api.stripe.com",
    "filters": { "includePaths": ["/v1/*"] }
  }'

# List saved configs
curl http://localhost:5770/ui/api/recorder/configs

# Export a config as JSON
curl http://localhost:5770/ui/api/recorder/configs/<config-id>/export -o config.json

# Import a config from JSON
curl -X POST http://localhost:5770/ui/api/recorder/configs/import \
  -H "Content-Type: application/json" \
  -d @config.json

Real-Time Streaming

Connect a WebSocket to receive entries as they are captured:

ws://localhost:5770/ui/api/recorder/<session-id>/ws

Each message is a JSON object:

{
  "type": "entry",
  "entry": {
    "id": "...",
    "entryType": "http",
    "request": { "method": "GET", "url": "..." },
    "response": { "statusCode": 200 },
    "durationMs": 42,
    "timings": { "dnsMs": 2, "connectMs": 5, "tlsMs": 12, "waitMs": 20, "totalMs": 42 }
  }
}

An eviction notification looks like:

{ "type": "entry", "entry": { "id": "__evict__", "notes": "<evicted-entry-id>" } }

Entry Annotations

Tag and annotate individual entries for later reference:

curl -X PATCH http://localhost:5770/ui/api/recorder/<session-id>/entries/<entry-id> \
  -H "Content-Type: application/json" \
  -d '{
    "tags": ["bug", "timeout"],
    "notes": "This request took 8 seconds — investigate upstream latency"
  }'

Entry Replay

Replay a captured request against the original (or a different) server:

curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/entries/<entry-id>/replay \
  -H "Content-Type: application/json" \
  -d '{
    "url": "http://localhost:5770/api/users/123",
    "headers": { "Authorization": "Bearer new-token" }
  }'

Override any field (method, url, headers, body) or leave the body empty to replay as-is.


API Reference

All endpoints are under /ui/api/recorder. Authentication required.

Sessions

Method Path Description
POST /start Start a new recording session
GET /sessions List sessions for the current user
GET /:id Get a single session
POST /:id/stop Stop a running session
POST /:id/restart Restart a stopped session (same config, new port if needed)
DELETE /:id Delete a session and its entries

Entries

Method Path Description
GET /:id/entries?offset=0&limit=100 List entries (paginated)
PATCH /:id/entries/:entryId Annotate an entry (tags, notes)
POST /:id/entries/:entryId/replay Replay a captured request
GET /:id/ws WebSocket stream of new entries

Export

Method Path Description
POST /:id/export Export as HAR file
POST /:id/export-perf Export as performance script
POST /:id/export-test Export as test script
POST /:id/export-collection Export as API Tester collection
POST /:id/mocks Generate Mockarty mocks from entries

Modifications

Method Path Description
GET /:id/modifications Get current modification rules
PUT /:id/modifications Update modification rules (live)

CA Certificate (MITM)

Method Path Description
GET /ca/status Check if a CA exists
POST /ca/generate Generate (or return existing) CA
GET /ca/download Download CA certificate PEM file

Saved Configurations

Method Path Description
GET /configs List saved configs
POST /configs Save a new config (max 10 per user)
DELETE /configs/:id Delete a saved config
GET /configs/:id/export Export config as JSON file
POST /configs/import Import config from JSON

Utility

Method Path Description
GET /ports Port pool status (used/max/details)
GET /port-check?port=8085 Check if a port is available

Practical Examples

Example 1: Recording a Payment API Integration

Record all traffic between your checkout service and Stripe during a test purchase:

# 1. Start a recording session
curl -X POST http://localhost:5770/ui/api/recorder/start \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Checkout Flow",
    "mode": "reverse",
    "targetUrl": "https://api.stripe.com",
    "filters": {
      "includePaths": ["/v1/charges", "/v1/payment_intents", "/v1/customers"],
      "includeMethods": ["POST", "GET"]
    }
  }'
# Returns session ID and listen port (e.g. 8081)

# 2. Point your checkout service at the recorder
export STRIPE_API_BASE=http://localhost:8081

# 3. Run your test purchase flow
./run-checkout-tests.sh

# 4. Stop the session
curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/stop

Example 2: Generating Mocks from a Recording

After recording, convert captured traffic into mocks that replay the same responses:

curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/mocks \
  -H "Content-Type: application/json" \
  -d '{
    "namespace": "checkout-tests",
    "prefix": "stripe-",
    "tags": ["stripe", "recorded"]
  }'

Now your checkout tests can run against Mockarty mocks with no network dependency.

Example 3: Creating Regression Tests

Export the recording as a test collection that asserts status codes and response shapes:

curl -X POST http://localhost:5770/ui/api/recorder/<session-id>/export-collection \
  -H "Content-Type: application/json" \
  -d '{
    "collectionName": "Stripe Regression Suite",
    "protocol": "tests"
  }'

The collection appears in the API Tester and can be run on every CI build.

Example 4: Chaos Testing with Toxics

Simulate a degraded Stripe API to test your retry and timeout logic:

curl -X POST http://localhost:5770/ui/api/recorder/start \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Stripe Chaos Test",
    "mode": "reverse",
    "targetUrl": "https://api.stripe.com",
    "toxics": {
      "delayMs": 3000,
      "delayJitter": 1000,
      "errorRate": 0.2
    }
  }'

20% of requests will return HTTP 503, and the remaining 80% will have 2-4 seconds of added latency.


Supported Entry Types

The recorder captures three types of traffic:

Type Description
http Standard HTTP request/response pairs
websocket WebSocket connections with individual frame capture
sse Server-Sent Event streams with individual event capture

GraphQL requests are automatically detected and annotated with operation name and type in the graphqlInfo field.


See Also