---
title: "Ports and the effective port"
description: "Each workspace owns a port pair: 4317/4318 for the first, 4319/4320 for the second. When a port is busy, the receiver moves along a fixed ladder. Always copy the port the app shows now."
source: "https://getloggerhead.com/docs/getting-started/ports-and-the-effective-port/"
---

# Ports and the effective port

> Each workspace owns a port pair: 4317/4318 for the first, 4319/4320 for the second. When a port is busy, the receiver moves along a fixed ladder. Always copy the port the app shows now.

The root receiver prefers port **4317** for gRPC and port **4318** for HTTP. These are the standard collector ports, so an SDK or an example finds the root without configuration.

## One port pair per workspace

Ports belong to the workspace. The first workspace takes 4317/4318, the second takes 4319/4320, the third takes 4321/4322, and so on. A new workspace takes the first pair no workspace holds, and the New workspace sheet shows the pair it picked. The sender picks the workspace by the port it exports to; the environment inside the workspace comes from the `deployment.environment.name` tag. See [Workspaces and environments](/docs/getting-started/workspaces-and-environments/).

| Workspace | gRPC | HTTP |
| --- | --- | --- |
| First (Default) | 4317 | 4318 |
| Second | 4319 | 4320 |
| Third | 4321 | 4322 |

The Workspaces page under MANAGE shows the pair that each workspace asks for. When a port was busy, **Collectors → Loggerhead receiver → Connection** and the MCP tool `get_receiver_info` show the effective pair.

## What happens when a port is busy

A Docker port forward or another collector often holds 4317 or 4318. The workspace's receiver then moves along a fixed ladder. The ladder adds 10000, then 20000, to the busy port.

| Preferred | Second try | Third try |
| --- | --- | --- |
| 4317 | 14317 | 24317 |
| 4318 | 14318 | 24318 |

The ladder gives the same port at every launch, so a config that you write once keeps working. When every ladder port is busy too, the root takes a port from the operating system. That port changes at each launch.

:::note[Copy the effective port]
Do not assume 4317. Open **Collectors → Loggerhead receiver → Connection** and copy the port the app shows now. That is the effective port.
:::

## Read the port with your AI tool

The MCP server knows the effective ports. Tell your AI coding tool: "Ask Loggerhead which port to send telemetry to." The tool then calls `get_receiver_info`.

In this example, a Docker port forward holds 4317, so the gRPC receiver moved to 14317:

```json
{
  "otlpGrpcPort": 14317,
  "otlpHttpPort": 4318,
  "otlpGrpcConfiguredPort": 4317,
  "otlpHttpConfiguredPort": 4318,
  "otlpGrpcPortConflict": true,
  "otlpHttpPortConflict": false
}
```

| Field | Meaning |
| --- | --- |
| `otlpGrpcPort`, `otlpHttpPort` | The effective ports. Send telemetry to these ports. |
| `otlpGrpcConfiguredPort`, `otlpHttpConfiguredPort` | The ports that the workspace asked for. |
| `otlpGrpcPortConflict`, `otlpHttpPortConflict` | `true` when the port was busy and the receiver moved. |

The top-level fields describe the workspace that the app shows. The `workspaces` array gives the same fields for each workspace. See [Tools reference](/docs/mcp-server/tools-reference/#get_receiver_info) for the full answer, and [Local endpoints](/docs/reference/http-api/) for the other services that the app serves on loopback.

## Find what holds the port

Open **Terminal** and run this command. It lists the process on each of the two ports.

```bash
lsof -nP -iTCP -sTCP:LISTEN | grep -E ':(4317|4318) '
```

Quit that process, or keep it and use the effective port. Both work.
