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

# Port (TCP) Monitoring

> Check that a TCP port accepts connections, with optional protocol banner checks for mail and FTP servers

A port monitor opens a TCP connection to a host and port and succeeds when the connection is accepted. For some protocols it can also check the server's greeting banner or a response.

## When to use it

* Databases: MySQL (3306), PostgreSQL (5432), MongoDB (27017), Redis (6379)
* Mail servers: SMTP (25, 465, 587), POP3 (110, 995), IMAP (143, 993)
* SSH (22), FTP (21) and custom TCP services

For web services on ports 80 and 443, use an [HTTP monitor](/monitors/http) instead: it validates far more.

<Note>
  Port checks run from UptimeIO's probe locations over the public internet, so the target must be publicly reachable. Private and internal targets (private IP ranges such as 10.x, 172.16-31.x and 192.168.x, `localhost`, and names ending in `.local`, `.internal` or `.lan`) are rejected with a `VALIDATION_ERROR`. Allow the connection through your firewall or security group.
</Note>

## Create a port monitor

<Steps>
  <Step title="Enter the target and port">
    A public hostname or IP address, and the TCP port (1 to 65535).
  </Step>

  <Step title="Choose a protocol">
    Pick the protocol of the service, or `generic` for a plain connection test. The protocol decides which optional checks are available.
  </Step>

  <Step title="Set interval and locations">
    The interval minimum depends on your plan (Free 300 seconds, Pro and Scale 60 seconds). Pro and Scale can choose probe locations; Free uses automatic selection.
  </Step>
</Steps>

### Settings

| Field (API) | Description | Default |
| - | - | - |
| `name` | Monitor name, up to 80 characters | Required |
| `type` | `TCP` | Required |
| `target` | Hostname or IP address | Required |
| `interval_seconds` | Seconds between checks | Required |
| `timeout_ms` | Maximum wait, 1,000 to 60,000. Must be shorter than the check interval. | `10000` |
| `monitoring_regions` | Probe locations; `[]` for automatic. Free must send `[]` | Required |
| `tcp_config.port` | TCP port, 1 to 65535 | Required |
| `tcp_config.protocol` | One of the protocol values below | `generic` |
| `tcp_config.protocol_validation` | Optional protocol checks (below) | none |

### Protocols

`tcp_config.protocol` accepts exactly these values:

| Value | Optional check |
| - | - |
| `generic` | None. Connection test only. |
| `ssh` | None. Connection test only (the SSH banner is not checked). |
| `smtp` | `protocol_validation.smtp`: `expect_banner` (expects a greeting containing `220`) and `test_command` (text sent after connecting). |
| `pop3` | `protocol_validation.pop3.expect_banner` (expects `+OK`). |
| `imap` | `protocol_validation.imap.expect_banner` (expects `* OK`). |
| `ftp` | `protocol_validation.ftp.expect_banner` (expects `220`). |
| `http` | `protocol_validation.http`: `path` (text sent after connecting) and `expected_response` (text expected in the reply). |
| `https` | Same options as `http`. |

<Info>
  The `http` and `https` protocols are raw TCP checks: the `path` text is sent as-is and the reply is searched for `expected_response`. No TLS handshake or HTTP parsing is done. For real HTTP checks use an HTTP monitor.
</Info>

### Example: connection test

```bash theme={null}
curl -X POST https://api.uptimeio.com/api/monitors \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production PostgreSQL",
    "type": "TCP",
    "target": "db.yourcompany.com",
    "interval_seconds": 300,
    "timeout_ms": 10000,
    "monitoring_regions": [],
    "tcp_config": { "port": 5432, "protocol": "generic" }
  }'
```

### Example: SMTP banner check

```bash theme={null}
curl -X POST https://api.uptimeio.com/api/monitors \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mail server",
    "type": "TCP",
    "target": "mail.yourcompany.com",
    "interval_seconds": 300,
    "monitoring_regions": [],
    "tcp_config": {
      "port": 25,
      "protocol": "smtp",
      "protocol_validation": { "smtp": { "expect_banner": true } }
    }
  }'
```

## How a check decides

* **No send data and no expected response**: succeeds as soon as the TCP connection is established.
* **Send data only**: succeeds once the data is written.
* **Expected response** (banner checks, or `http`/`https` `expected_response`): succeeds when the server's reply contains the expected text, and fails otherwise.

## Common ports

| Service | Port | Service | Port |
| - | - | - | - |
| MySQL | 3306 | SMTP | 25 / 587 / 465 |
| PostgreSQL | 5432 | POP3 | 110 / 995 |
| MongoDB | 27017 | IMAP | 143 / 993 |
| Redis | 6379 | SSH / SFTP | 22 |
| SQL Server | 1433 | FTP | 21 |

## Best practices

* Use a banner check for mail and FTP servers: an open port does not prove the service answers correctly.
* Keep the timeout around 5-10 seconds.
* Combine with [Ping](/monitors/ping) (is the host up?) and [HTTP](/monitors/http) (does the application work?).
* A port monitor proves connectivity only. The service can accept connections while authentication is broken.
* Do not expose databases to the whole internet just to monitor them. Restrict access with a firewall where you can.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connection refused">
    Nothing is listening on that port, the port is wrong, or the service only listens on localhost. Check with `nc -zv hostname port` and the service's bind address.
  </Accordion>

  <Accordion title="Connection timeout">
    A firewall is dropping the traffic, the host is unreachable, or `timeout_ms` is too low. Allow the connection and check firewall logs.
  </Accordion>

  <Accordion title="Expected response not found">
    The server's reply did not contain the expected text. The port may be served by a different service or a proxy. Check the banner manually with `nc hostname port`.
  </Accordion>

  <Accordion title="VALIDATION_ERROR on the target">
    The target is private, internal, a test domain or one of UptimeIO's own domains. Use a public hostname or IP.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="HTTP Monitoring" icon="globe" href="/monitors/http">
    Monitor web services and APIs
  </Card>

  <Card title="Notifications" icon="bell" href="/notifications/overview">
    Configure alerts for port monitors
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.