diff --git a/constructs/traceroute-monitor.mdx b/constructs/traceroute-monitor.mdx
new file mode 100644
index 00000000..735de888
--- /dev/null
+++ b/constructs/traceroute-monitor.mdx
@@ -0,0 +1,267 @@
+---
+title: 'TracerouteMonitor Construct'
+description: 'Learn how to configure Traceroute monitors with the Checkly CLI.'
+sidebarTitle: 'Traceroute Monitor'
+---
+
+import GeneralMonitorOptionsTable from '/snippets/general-monitor-options-table.mdx';
+
+
+Learn more about Traceroute Monitors in [the Traceroute monitor overview](/detect/uptime-monitoring/traceroute-monitors/overview).
+
+
+Traceroute monitors map the network path to a host hop-by-hop, measuring per-hop latency and packet loss, and detecting whether the destination is reached. Use them to monitor path stability and catch routing issues before they affect your users.
+
+
+Before creating Traceroute Monitors, ensure you have:
+
+- An initialized Checkly CLI project
+- A hostname or IP address you want to trace
+- Basic understanding of network tracing (traceroute / tracert)
+
+For additional setup information, see [CLI overview](/cli/overview).
+
+
+
+
+```ts Basic Example
+import { Frequency, TracerouteMonitor } from "checkly/constructs"
+
+new TracerouteMonitor('traceroute-api', {
+ name: 'API Gateway Network Path',
+ description: "Maps the network path to `api.example.com` to detect routing changes.",
+ frequency: Frequency.EVERY_5M,
+ request: {
+ url: 'api.example.com',
+ },
+})
+```
+
+```ts Advanced Example
+import { Frequency, TracerouteAssertionBuilder, TracerouteMonitor } from "checkly/constructs"
+
+new TracerouteMonitor('traceroute-db', {
+ name: 'Database Routing Monitor',
+ description: "Traces path to `db.example.com` with strict latency and hop assertions.",
+ activated: true,
+ frequency: Frequency.EVERY_10M,
+ locations: ['us-east-1', 'eu-central-1'],
+ degradedResponseTime: 10000,
+ maxResponseTime: 20000,
+ request: {
+ url: 'db.example.com',
+ protocol: 'TCP',
+ port: 5432,
+ ipFamily: 'IPv4',
+ maxHops: 20,
+ maxUnknownHops: 10,
+ ptrLookup: true,
+ timeout: 15,
+ assertions: [
+ TracerouteAssertionBuilder.hopCount().lessThan(15),
+ TracerouteAssertionBuilder.responseTime().avg().lessThan(50),
+ TracerouteAssertionBuilder.packetLoss().lessThan(5),
+ ],
+ },
+})
+```
+
+
+
+## Configuration
+
+Traceroute monitors have their own probe-specific settings, plus the standard monitor options shared across all check types.
+
+
+
+
+| Parameter | Type | Required | Default | Description |
+|-----------|------|----------|---------|-------------|
+| `request` | `object` | ✅ | - | Traceroute request configuration object |
+| `degradedResponseTime` | `number` | ❌ | `10000` | Final-hop avg RTT in milliseconds at which the monitor is marked as degraded |
+| `maxResponseTime` | `number` | ❌ | `20000` | Final-hop avg RTT in milliseconds at which the monitor is marked as failed |
+
+
+
+
+
+
+
+
+
+### `TracerouteMonitor` Options
+
+
+
+Traceroute request configuration, including probe protocol, target host, and response validation.
+
+**Usage:**
+
+```ts
+new TracerouteMonitor('traceroute-monitor', {
+ name: 'Network Path Monitor',
+ request: {
+ url: 'api.example.com',
+ protocol: 'TCP',
+ port: 443,
+ assertions: [
+ TracerouteAssertionBuilder.hopCount().lessThan(20),
+ ],
+ },
+})
+```
+
+**Parameters:**
+
+| Parameter | Type | Required | Default | Description |
+|-----------|------|----------|---------|-------------|
+| `url` | `string` | ✅ | - | Target hostname or IP address. Do not include a scheme or port |
+| `protocol` | `string` | ❌ | `'TCP'` | Probe protocol: `'TCP'` \| `'UDP'` \| `'ICMP'` \| `'SCTP'` |
+| `port` | `number` | ❌ | `443` | Destination port (1–65535). Defaults to `443` for all non-ICMP protocols. For UDP/SCTP, set `port: 33434` explicitly — a high closed port so the destination returns ICMP Unreachable to confirm arrival. Ignored when `protocol` is `'ICMP'` |
+| `ipFamily` | `string` | ❌ | `'IPv4'` | IP family: `'IPv4'` \| `'IPv6'` |
+| `maxHops` | `number` | ❌ | `30` | Maximum hops to probe (1–64) |
+| `maxUnknownHops` | `number` | ❌ | `15` | Maximum consecutive unresponsive hops before stopping (1–30) |
+| `ptrLookup` | `boolean` | ❌ | `true` | Perform reverse-DNS (PTR) lookups on hop IPs |
+| `timeout` | `number` | ❌ | `10` | Seconds to wait for the trace to complete (1–30) |
+| `assertions` | `TracerouteAssertion[]` | ❌ | `[]` | Response assertions using `TracerouteAssertionBuilder` |
+
+
+
+
+Final-hop average RTT in milliseconds at which the monitor is marked as degraded (warning state). Maximum: 30,000.
+
+**Usage:**
+
+```ts highlight={3}
+new TracerouteMonitor("traceroute-latency-tiers", {
+ name: "API Network Path",
+ degradedResponseTime: 5000, // Warn when final-hop avg RTT exceeds 5 seconds
+ request: {
+ url: 'api.example.com',
+ },
+})
+```
+
+
+
+Final-hop average RTT in milliseconds at which the monitor is marked as failed. Maximum: 30,000.
+
+**Usage:**
+
+```ts highlight={3}
+new TracerouteMonitor("traceroute-latency-tiers", {
+ name: "API Network Path",
+ maxResponseTime: 15000, // Fail when final-hop avg RTT exceeds 15 seconds
+ request: {
+ url: 'api.example.com',
+ },
+})
+```
+
+
+### `TracerouteMonitor` Assertions
+
+Assertions for Traceroute monitors are defined using the `TracerouteAssertionBuilder`. The following sources are available:
+
+- `responseTime(property?)`: Validate RTT at the final responding hop. Defaults to the `avg` property. Use `.avg()`, `.min()`, `.max()`, or `.stdDev()` to target a specific statistic. This assertion fails when `destinationReached` is `false`
+- `hopCount()`: Assert against the total number of hops recorded in the trace
+- `packetLoss()`: Assert against the packet loss percentage at the last recorded hop (0–100)
+
+Here are some examples:
+
+- Assert that the average final-hop latency is below a threshold (default property is `avg`):
+
+```ts
+TracerouteAssertionBuilder.responseTime().lessThan(100)
+// Equivalent to:
+{ source: 'RESPONSE_TIME', property: 'avg', comparison: 'LESS_THAN', target: '100' }
+```
+
+- Assert against a specific RTT property:
+
+```ts
+TracerouteAssertionBuilder.responseTime().max().lessThan(200)
+// Equivalent to:
+{ source: 'RESPONSE_TIME', property: 'max', comparison: 'LESS_THAN', target: '200' }
+```
+
+- Assert on the number of hops:
+
+```ts
+TracerouteAssertionBuilder.hopCount().lessThan(15)
+// Equivalent to:
+{ source: 'HOP_COUNT', comparison: 'LESS_THAN', target: '15' }
+```
+
+- Assert on packet loss at the last hop:
+
+```ts
+TracerouteAssertionBuilder.packetLoss().lessThan(10)
+// Equivalent to:
+{ source: 'PACKET_LOSS', comparison: 'LESS_THAN', target: '10' }
+```
+
+Learn more in our docs on [Assertions](/detect/assertions).
+
+### General Monitor Options
+
+
+Friendly name for your Traceroute Monitor that will be displayed in the Checkly dashboard and used in notifications.
+
+**Usage:**
+
+```ts highlight={2}
+new TracerouteMonitor("my-traceroute", {
+ name: "API Gateway Network Path",
+ /* More options ... */
+})
+```
+
+
+
+How often the Traceroute Monitor should run. Use the `Frequency` enum to set the check interval.
+
+**Usage:**
+
+```ts highlight={3}
+new TracerouteMonitor("my-traceroute", {
+ name: "API Gateway Network Path",
+ frequency: Frequency.EVERY_5M,
+ /* More options ... */
+})
+```
+
+**Available frequencies**: `EVERY_30S`, `EVERY_1M`, `EVERY_2M`, `EVERY_5M`, `EVERY_10M`, `EVERY_15M`, `EVERY_30M`, `EVERY_1H`, `EVERY_2H`, `EVERY_3H`, `EVERY_6H`, `EVERY_12H`, `EVERY_24H`. Traceroute monitors do not support sub-30-second frequencies (`EVERY_10S` / `EVERY_20S`).
+
+
+
+Array of [public location codes](/concepts/locations/#public-locations) where the Traceroute Monitor should run from. Use `privateLocations` for [private locations](/platform/private-locations/overview). Multiple locations help detect regional routing differences.
+
+**Usage:**
+
+```ts highlight={3}
+new TracerouteMonitor("global-path-monitor", {
+ name: "API Path from Multiple Regions",
+ locations: ["us-east-1", "eu-central-1", "ap-southeast-1"],
+ request: {
+ url: 'api.example.com',
+ },
+})
+```
+
+
+
+Whether the Traceroute Monitor is enabled and will run according to its schedule.
+
+**Usage:**
+
+```ts highlight={3}
+new TracerouteMonitor("my-traceroute", {
+ name: "API Gateway Network Path",
+ activated: false, // Disabled monitor
+ request: {
+ url: 'api.example.com',
+ },
+})
+```
+
diff --git a/detect/uptime-monitoring/traceroute-monitors/configuration.mdx b/detect/uptime-monitoring/traceroute-monitors/configuration.mdx
new file mode 100644
index 00000000..bcaf3bf4
--- /dev/null
+++ b/detect/uptime-monitoring/traceroute-monitors/configuration.mdx
@@ -0,0 +1,111 @@
+---
+title: 'Traceroute Monitor Configuration'
+description: 'Configure your Traceroute monitor to map network paths and detect routing issues, latency, and packet loss.'
+sidebarTitle: 'Configuration'
+---
+
+
+To configure a Traceroute monitor using code, learn more about the [Traceroute Monitor Construct](/constructs/traceroute-monitor).
+
+
+### Basic Setup
+
+Configure your Traceroute monitor by specifying the target host and probe parameters:
+
+* **Hostname or IP address:** The host to trace to (e.g. `api.example.com` or `203.0.113.1`). Do not include a scheme or port in this field
+* **IP family:** Choose between IPv4 (default) or IPv6
+* **Protocol:** The probe protocol. TCP (default) is the most firewall-friendly option. See the [protocol reference](/detect/uptime-monitoring/traceroute-monitors/overview#probe-protocols) for details on TCP, UDP, ICMP, and SCTP
+* **Port:** Destination port for TCP, UDP, and SCTP probes (1–65535). Defaults to `443` for TCP and `33434` for UDP/SCTP. Not applicable for ICMP — the port field is hidden when ICMP is selected
+* **Max Hops:** Maximum number of hops to probe before stopping (1–64, default: 30)
+* **Max Unknown Hops:** Maximum number of consecutive unresponsive hops to tolerate before cutting the trace short (1–30, default: 15). Many routers silently drop traceroute probes without affecting real traffic, so a reasonable limit prevents traces from halting unnecessarily
+* **Timeout:** Maximum time in seconds to wait for the entire trace to complete (1–30, default: 10)
+* **Reverse DNS (PTR lookup):** When enabled (default: on), Checkly performs a PTR lookup on each hop IP to resolve it to a hostname. Disable to reduce trace time when hostnames are not needed
+
+### Assertions
+
+Use assertions to validate Traceroute results and alert when paths change or degrade:
+
+You can create assertions based on:
+
+* **Latency:** RTT statistics for the **final responding hop**. Available properties: `avg`, `min`, `max`, `stdDev` (all in milliseconds). This assertion requires the destination to be reached — if `destinationReached` is `false`, `finalHopLatency` is absent and the assertion fails
+* **Hop Count:** Total number of hops recorded in the trace. Use this to detect routing changes that add or remove hops from the expected path
+* **Packet Loss:** Packet loss percentage at the **last recorded hop** (0–100). A non-zero value indicates that some probe packets were not returned
+
+For more details, see [Assertions](/detect/assertions).
+
+### Response Time Limits
+
+Set performance thresholds based on final-hop latency:
+
+* **Degraded After:** Final-hop avg RTT threshold (in milliseconds) after which the check is marked as degraded but not failed. Default: 3,000 ms. Maximum: 30,000 ms
+* **Failed After:** Final-hop avg RTT threshold after which the check fails completely. Default: 5,000 ms. Maximum: 30,000 ms
+
+
+Response-time thresholds apply to the **final-hop average RTT**, not the total check execution time. If the destination is not reached, the monitor is marked as failed regardless of these thresholds.
+
+
+### JSON Response Schema
+
+The Traceroute response is available as structured JSON. All responses share this format:
+
+```json
+{
+ "hostname": "api.example.com", // Target hostname or IP as configured
+ "resolvedIp": "93.184.216.34", // IP address used for the trace
+ "port": 443, // Destination port; always present (0 for ICMP probes)
+ "ipFamily": "IPv4", // "IPv4" or "IPv6"
+ "maxHops": 30, // Configured max hops
+ "totalHops": 12, // Number of hops actually recorded
+ "destinationReached": true, // Whether the destination responded
+ "truncationReason": "destinationReached",// Why the trace stopped:
+ // "destinationReached" | "maxHops" | "maxUnknownHops" | "timeout"
+ "probeProtocol": "TCP", // Probe protocol: "TCP" | "UDP" | "ICMP" | "SCTP"
+ "finalHopLatency": { // RTT stats for the last responding hop
+ "avg": 12.34, // Omitted entirely (field absent) when destination is not reached
+ "min": 11.80,
+ "max": 13.10,
+ "stdDev": 0.42
+ },
+ "hops": [
+ {
+ "hop_number": 1,
+ "main_ip": "10.0.0.1", // Primary IP observed at this hop
+ "main_host": "router.isp.net", // Reverse-DNS hostname (empty when PTR lookup is off or lookup fails)
+ "sent": 3, // Probe packets sent to this hop
+ "received": 3, // Replies received from this hop
+ "loss_percentage": 0.0, // Packet loss at this hop
+ "rtt": {
+ "last_ms": 1.23, // RTT of the most recent probe
+ "avg_ms": 1.10, // Average RTT across all probes
+ "best_ms": 0.95, // Minimum RTT
+ "worst_ms": 1.23, // Maximum RTT
+ "stddev_ms": 0.12 // Standard deviation
+ },
+ "asn": 15169, // Autonomous System Number (0 if unknown)
+ "asn_org": "GOOGLE", // AS organization name
+ "country": "US", // Two-letter country code
+ "aws_region": "", // AWS region name (if hop is in AWS)
+ "aws_service": "" // AWS service name (if hop is in AWS)
+ }
+ // ... one entry per recorded hop
+ ],
+ "timestamp": 1720000000 // Unix timestamp of the trace run
+}
+```
+
+### Frequency
+
+Set how often the monitor runs. Traceroute monitors run at most **once every 30 seconds** (every 30 seconds to 24 hours) — the two sub-30-second frequencies aren't available.
+
+### Scheduling & Locations
+
+* **Strategy:** Choose between round-robin or parallel execution. Learn more about [scheduling strategies](/concepts/scheduling)
+* **Locations:** Select [public](/concepts/locations/#public-locations) or [private](/platform/private-locations/overview) locations to run the monitor from
+
+### Additional Settings
+
+* **Name:** Give your monitor a clear name to identify it in dashboards and alerts
+* **Description:** Add context about what this monitor does and why it matters. Supports markdown, max 500 characters. When a failure occurs, [Rocky AI](/ai/rocky-ai) uses the description to provide more accurate [root cause and user impact analysis](/resolve/ai-root-cause-analysis/overview)
+* **Tags:** Use tags to organize monitors across [dashboards](/communicate/dashboards/overview/) and [maintenance windows](/communicate/maintenance-windows/overview)
+* **Retries:** Define how failed runs should be retried. See [retry strategies](/communicate/alerts/retries)
+* **Alerting:** Configure your [alert settings](/communicate/alerts/configuration), [alert channels](/communicate/alerts/channels), or set up [webhooks](/integrations/alerts/webhooks) for custom integrations
diff --git a/detect/uptime-monitoring/traceroute-monitors/overview.mdx b/detect/uptime-monitoring/traceroute-monitors/overview.mdx
new file mode 100644
index 00000000..b9e04444
--- /dev/null
+++ b/detect/uptime-monitoring/traceroute-monitors/overview.mdx
@@ -0,0 +1,109 @@
+---
+title: 'Traceroute Monitors Overview'
+description: 'Map the network path to any host and detect routing issues, high-latency hops, and packet loss.'
+sidebarTitle: Overview
+---
+
+
+**Monitoring as Code**: Learn more about the [Traceroute Monitor Construct](/constructs/traceroute-monitor).
+
+
+## What are Traceroute Monitors?
+
+Traceroute monitors map the network path between a Checkly location and your target host, recording every router hop along the way and measuring per-hop latency and packet loss. Typical use cases include:
+
+* Detecting routing anomalies or unexpected path changes between Checkly locations and your infrastructure
+* Identifying which network segment is responsible for latency spikes or packet loss
+* Verifying that the destination is reachable end-to-end, beyond just confirming that a port accepts connections
+* Continuously monitoring path stability across regions over time
+
+## How do Traceroute Monitors work?
+
+A Traceroute monitor executes the following steps on each run:
+
+1. **Hostname resolution**: If a hostname is provided, Checkly resolves it to an IP address before sending any probes
+2. **Probe execution**: The runner sends probe packets using the configured protocol (TCP by default). Each probe carries a progressively higher TTL so each router on the path responds with an ICMP Time Exceeded message before forwarding the packet
+3. **Hop collection**: RTT statistics (avg, min, max, stddev) and packet loss are collected for each router hop along the path
+4. **Destination detection**: When the destination host responds directly, the trace is complete and `destinationReached` is set to `true`
+5. **Assertion evaluation**: Configured assertions are evaluated against the results — including final-hop latency, total hop count, and last-hop packet loss
+
+### Probe protocols
+
+| Protocol | Default port | How destination is detected |
+|----------|-------------|---------------------------|
+| **TCP** (default) | 443 | SYN-ACK or RST received from destination |
+| **UDP** | 33434 | Any ICMP Destination Unreachable from the target (port unreachable, admin-prohibited, host unreachable, etc.) |
+| **ICMP** | *(no port)* | Echo Reply from destination |
+| **SCTP** | 33434 | SCTP ABORT or INIT-ACK from destination, or ICMP Destination Unreachable from the target |
+
+
+The default port for UDP and SCTP in the Checkly web UI is pre-filled to `33434` — a high, typically-closed port where the destination is more likely to return an ICMP Destination Unreachable. When configuring via the CLI or API, the port defaults to `443` for all non-ICMP protocols, so set `port: 33434` explicitly for UDP/SCTP probes if you want the same behavior.
+
+
+## Traceroute Monitor Results
+
+Select a specific check run to inspect its results:
+
+* **Summary:** Shows the target hostname, resolved IP, monitor state (`passed`, `degraded`, or `failed`), total hop count, and whether the destination was reached
+
+* **Error details:** If the trace failed — due to a DNS resolution error, an unreachable network, or assertion failures — the error message is shown here
+
+* **Hop-by-hop table:** Each hop shows:
+ * Hop number and primary IP address, with reverse-DNS hostname when PTR lookup is enabled
+ * ASN, organization name, and country
+ * AWS region and service (where applicable)
+ * Probes sent and received, plus packet loss percentage
+ * RTT statistics: last, avg, best, worst, and stddev in milliseconds
+
+* **Final-hop latency:** RTT statistics for the destination hop. This is the value used for `Latency` assertions and the degraded/failed response-time thresholds
+
+Learn more in our documentation on [Results](/concepts/results).
+
+## Troubleshooting Common Issues
+
+
+**Symptom**: `destinationReached` is `false`, yet the website or API responds normally.
+
+**Root causes**:
+* The configured port is firewalled — TCP SYN probes never receive a SYN-ACK or RST
+* The target host silently drops probe packets at the network edge
+* A middle-box rewrites or discards probe traffic before it reaches the destination
+
+**How to fix**:
+1. Switch the probe protocol — try `ICMP` if the host responds to ping, or `UDP` for a connectionless probe
+2. Change the port to one that is explicitly open on the target (e.g. `80` or `22`)
+3. Confirm reachability at the application layer with an [API Monitor](/detect/synthetic-monitoring/overview) or [TCP Monitor](/detect/uptime-monitoring/tcp-monitors/overview) targeting the same host and port
+
+
+
+**Symptom**: Several intermediate hops show no response, but the destination is eventually reached.
+
+**Root cause**: Routers commonly deprioritize or filter ICMP Time Exceeded replies for probe traffic without affecting real data forwarding. The hops are still routing your packets — they simply do not respond to traceroute probes.
+
+**What to do**:
+* Focus on `destinationReached` and final-hop latency rather than individual intermediate hops
+* If the trace is cut short before the destination, increase the `Max Unknown Hops` limit
+
+
+
+**Symptom**: SCTP probes fail with a socket permission error on a self-hosted Checkly Agent.
+
+**Root cause**: SCTP probes require raw sockets, which need `CAP_NET_RAW`. Container runtimes drop this capability by default.
+
+**How to fix** — In **Kubernetes**, update your pod spec or Helm values:
+
+```yaml
+securityContext:
+ allowPrivilegeEscalation: true
+ capabilities:
+ add: ["NET_RAW"]
+```
+
+In **Docker**:
+
+```bash
+docker run --cap-add=NET_RAW ghcr.io/checkly/agent:latest
+```
+
+`CAP_NET_RAW` only grants permission to open raw sockets. It does not escalate broader container privileges.
+
diff --git a/docs.json b/docs.json
index abfd76d5..edd6ad73 100644
--- a/docs.json
+++ b/docs.json
@@ -167,6 +167,13 @@
"detect/uptime-monitoring/icmp-monitors/configuration"
]
},
+ {
+ "group": "Traceroute Monitors",
+ "pages": [
+ "detect/uptime-monitoring/traceroute-monitors/overview",
+ "detect/uptime-monitoring/traceroute-monitors/configuration"
+ ]
+ },
{
"group": "Heartbeat Monitors",
"pages": [
@@ -481,6 +488,7 @@
"constructs/dns-monitor",
"constructs/tcp-monitor",
"constructs/icmp-monitor",
+ "constructs/traceroute-monitor",
"constructs/heartbeat-monitor",
"constructs/agentic-check",
"constructs/api-check",