---
name: ipcheck
description: Get the current public IP address and IPv4/IPv6 network-stack status of your execution environment using the free qwo.moe IP echo services (dual-stack https://ip.qwo.moe, IPv4-only https://ip4.qwo.moe, IPv6-only https://ip6.qwo.moe). Use it when you need to report the outbound IP, verify IPv4/IPv6 reachability, decide which protocol family a dual-stack connection actually prefers, or produce machine-readable {ip,type} results for other tools.
---

# IP & Network Stack Check (qwo.moe)

Zero-registration, CORS-enabled public service for IP and protocol-stack
diagnostics. AI agents and automation are explicitly welcome.

## Endpoints

| Host | Network | What it proves when reachable |
| --- | --- | --- |
| `https://ip.qwo.moe` | dual-stack | your IP; also which family the connection actually used |
| `https://ip4.qwo.moe` | IPv4 only (A only) | IPv4 egress works |
| `https://ip6.qwo.moe` | IPv6 only (AAAA only) | IPv6 egress works |

Query styles (identical on all three hosts):

| Request | Response |
| --- | --- |
| `https://HOST/` | human/docs page (HTML); not a machine result |
| `https://HOST/?text` | plain-text IP, one line |
| `https://HOST/?json` | `{"ip":"<addr>","type":"IPv4"|"IPv6"}` |

Always use `?text` (plain) or `?json` (structured) for machine reads —
the bare root URL returns the documentation page, not an IP.

## Recipes

### 1. Outbound IP (plain text)

```sh
curl -fsS --max-time 5 https://ip.qwo.moe/?text
# -> e.g. 8.8.8.8   (a single line; no decoration)
```

### 2. IP plus protocol family (structured)

```sh
curl -fsS --max-time 5 https://ip.qwo.moe/?json
# -> e.g. {"ip":"2001:2333::1","type":"IPv6"}
```

Parse with jq: `curl -fsS .../?json | jq -r .type`.

### 3. Force one family for the probe connection

```sh
curl -4 -fsS --max-time 5 https://ip.qwo.moe/?text   # force IPv4
curl -6 -fsS --max-time 5 https://ip.qwo.moe/?text   # force IPv6
```

### 4. Reachability + protocol preference (the full check)

Probe all three hosts concurrently (they share a client IP but resolve to
different families), then classify:

```sh
v4=$(curl -fsS --max-time 5 https://ip4.qwo.moe/?text || true)
v6=$(curl -fsS --max-time 5 https://ip6.qwo.moe/?text || true)
dual=$(curl -fsS --max-time 5 https://ip.qwo.moe/?text || true)
```

Classification semantics (this matches the site's own browser test):

| Condition | Verdict |
| --- | --- |
| `v4` ok, `v6` fails | `v4_only` |
| `v6` ok, `v4` fails | `v6_only` |
| both ok, `dual` contains `:` (IPv6) | `v6_prefer` (dual-stack connection went IPv6) |
| both ok, `dual` is an IPv4 literal | `v4_prefer` (dual-stack connection went IPv4) |

An IPv6 result always contains `:`; an IPv4 result never does. Empty/failed
probe = that family unreachable from your environment (e.g. no IPv6 route,
firewalled, or `curl` forced the wrong family with `-4/-6`).

## Usage notes

- HTTPS (and HTTP on port 80) both work; old TLS stacks are tolerated.
- No auth, no rate limit enforced — but please stay polite: one full check
  (3 requests) per task, reuse cached results within a task, add timeouts,
  and do not hammer in loops. Every request counts toward the service's
  public usage statistics.
- The server reads the real client address (`REMOTE_ADDR`), so the answer
  reflects your true egress point — useful for verifying proxies, VPNs,
  containers and CI runners.
- Responses carry `Cache-Control: no-store`; always fetch fresh when the
  egress might have changed.
- Example answer shape for a user: "Your current egress: 8.8.8.8
  (IPv4). IPv6 is not reachable from this environment (v4_only)."

## License / attribution

no restriction on using the endpoints themselves, Please do not misuse.
