Forcing IPv4 or IPv6 in cURL isolates one network path at a time when a dual-stack endpoint behaves differently across address families. That makes it useful for incident triage, path validation, and scripts that must prove whether one family works without silently using the other.

By default, cURL accepts the address families returned for a hostname and uses the first working connection path. The -4 or --ipv4 and -6 or --ipv6 options restrict the transfer to one family while leaving the request method, headers, body, and TLS behavior unchanged.

Family-forced requests only succeed when the target, local routing, and the network path all support the selected family. Missing AAAA records, blocked IPv6 transit, or an IPv4-only listener can all produce real connection failures, and some resolvers can still return compatibility-formatted results such as IPv4-mapped IPv6 addresses. Automation should treat an unavailable family as an explicit error instead of assuming fallback will rescue the request.

Steps to force IPv4 or IPv6 connections in cURL:

  1. Run one request without a family override to see which address family the current resolver and connection path choose by default.
    $ curl -sS -o /dev/null -w 'default=%{remote_ip}\n' https://example.com
    default=2001:db8:100::24

    The returned remote_ip may be either IPv4 or IPv6, depending on the resolver results and which path completes first on the current host. The example addresses in this page use documentation-only IP space.

  2. Force an IPv4-only connection with -4 when the transfer must ignore AAAA answers.
    $ curl -4 -sS -o /dev/null -w 'ipv4=%{remote_ip}\n' https://example.com
    ipv4=198.51.100.24

    The remote_ip value should be a dotted-quad address when the transfer actually used IPv4.

  3. Force an IPv6-only connection with -6 when validating a dual-stack service or preferring the IPv6 path explicitly.
    $ curl -6 -sS -o /dev/null -w 'ipv6=%{remote_ip}\n' https://example.com
    ipv6=2001:db8:100::24

    An IPv6-only request requires a reachable IPv6 route, and on macOS the resolver may still return IPv4-mapped IPv6 values such as ::ffff:192.0.0.170 for compatibility.

  4. Add verbose logging to confirm that cURL filtered the resolver results before the socket connected.
    $ curl --ipv4 --verbose --silent --show-error --output /dev/null https://example.com
    * Host example.com:443 was resolved.
    * IPv6: (none)
    * IPv4: 198.51.100.24, 198.51.100.25
    *   Trying 198.51.100.24:443...
    * Connected to example.com (198.51.100.24) port 443

    With --ipv6, the verbose transcript shows the inverse pattern: IPv6 candidates remain and the IPv4 list becomes (none). On macOS, those IPv6 candidates can include compatibility-formatted results such as ::ffff:192.0.0.170.

  5. Pair a family override with --max-time when an unavailable path must fail fast in automation.
    $ curl --ipv6 --max-time 5 --silent --show-error --output /dev/null --write-out 'remote=%{remote_ip} code=%{response_code}\n' http://ipv4only.arpa/
    curl: (28) Connection timed out after 5008 milliseconds
    remote= code=000

    The exact failure text varies by DNS, routing, and listener state, but an empty remote_ip with HTTP code 000 means no usable connection was established for the forced family.