RTSP 400 Bad Request Fix: DESCRIBE Failed, Malformed Camera URL, and Header Errors

Fix RTSP 400 Bad Request on DESCRIBE. Covers malformed camera URLs for Axis/Dahua/Hikvision, unsupported headers, reverse proxy issues, auth, and vendor-specific stream paths with real diagnostic commands.

rtsp 400 bad request, describe failed, camera url, ip camera troubleshooting, rtsp diagnostics, malformed rtsp url

RTSP/1.0 400 Bad Request means the camera rejected your RTSP request as malformed. It's not a network problem. It's not a codec problem. It's a request-format problem — and it's fixable once you see the exact request the camera received.

Fast answer: 30-second triage

  1. Test with VLC first. If VLC works, capture the exact RTSP request it sends. Compare to your failing client.
  2. Check the URL path. Different cameras use completely different paths for the same RTSP stream. Copying a URL from one camera brand to another is the #1 cause of 400 errors.
  3. Check URL encoding. Special characters in passwords break RTSP URL parsing. Encode @ as %40, : as %3A, / as %2F.
  4. Check for proxy interference. Direct RTSP to the camera works but through a proxy returns 400? The proxy is altering RTSP headers.

If none of these fix it, work through the detailed sections below.

First: verify the camera is reachable

Before debugging RTSP, confirm basic connectivity:

# TCP reachability
nc -zv 192.168.1.100 554

# Or with telnet
telnet 192.168.1.100 554

# RTSP OPTIONS — the simplest RTSP request
# If this fails, the camera isn't speaking RTSP

If the port is closed, the problem is network/firewall, not RTSP.

Camera-specific URL formats

The most common cause of 400 errors: using the wrong URL path format for your camera brand. Each manufacturer uses different conventions:

Axis

rtsp://<ip>/axis-media/media.amp
rtsp://<ip>/mpeg4/media.amp
rtsp://<ip>:554/axis-media/media.amp?videocodec=h264

Dahua

rtsp://<user>:<pass>@<ip>:554/cam/realmonitor?channel=1&subtype=0
rtsp://<user>:<pass>@<ip>:554/cam/realmonitor?channel=1&subtype=1
  • subtype=0: main stream
  • subtype=1: sub stream

Hikvision

rtsp://<user>:<pass>@<ip>:554/Streaming/Channels/101
rtsp://<user>:<pass>@<ip>:554/Streaming/Channels/102
  • 101: channel 1, main stream
  • 102: channel 1, sub stream
  • 201: channel 2, main stream

Generic / ONVIF

rtsp://<ip>:554/stream1
rtsp://<ip>:554/live
rtsp://<ip>:554/h264
rtsp://<ip>:554/h265
rtsp://<ip>:554/profile1/media.smp
rtsp://<ip>/onvif1
rtsp://<ip>/onvif2

Testing with ffmpeg

# Test DESCRIBE only (don't decode)
ffmpeg -rtsp_transport tcp -i "rtsp://user:pass@192.168.1.100:554/stream1" -t 1 -f null -

# Verbose output shows the exact RTSP exchange
ffmpeg -loglevel debug -rtsp_transport tcp -i "rtsp://..." -t 1 -f null - 2>&1 | grep -E "DESCRIBE|SETUP|response"

URL encoding: the silent 400 trigger

When a password contains special characters, the RTSP URL becomes ambiguous. The @ separates credentials from the host, so a password containing @ breaks the parsing.

WRONG: rtsp://admin:pa@ss@192.168.1.100/stream1
       parser sees: user=admin, pass=pa, host=ss@192.168.1.100

RIGHT:  rtsp://admin:pa%40ss@192.168.1.100/stream1
       parser sees: user=admin, pass=pa@ss, host=192.168.1.100

Characters that must be encoded in RTSP URLs:

Character Encoding Example
@ %40 user@domainuser%40domain
: %3A pass:wordpass%3Aword
/ %2F pass/wordpass%2Fword
? %3F in query values
# %23 in query values
% %25 literal percent
& %26 in query values (if not separating parameters)
space %20 in query values

Config files often add another layer of escaping. A URL in a YAML file may need both YAML escaping AND URL encoding.

Full diagnostic decision tree

RTSP returns 400 Bad Request
│
├─ Is port 554 reachable?
│  ├─ NO → Fix network/firewall. Not an RTSP issue.
│  └─ YES → Continue
│
├─ Does VLC play the same URL?
│  ├─ YES, VLC works → Capture VLC's exact request. Compare with your client.
│  │   Differences in headers, URI format, or auth will point to the fix.
│  └─ NO, VLC also fails → Problem is in the URL or camera config
│
├─ Check the URL path
│  ├─ Wrong manufacturer format → Use correct format for your camera brand
│  ├─ Query parameters missing → Add required parameters (channel, subtype)
│  └─ Path contains unencoded special chars → URL-encode credentials
│
├─ Check DESCRIBE headers
│  ├─ Missing Accept: application/sdp → Add it
│  ├─ Extra HTTP headers (via proxy) → Remove proxy from RTSP path
│  └─ Malformed Authorization → Fix Digest auth parameters
│
├─ Check CSeq and RTSP syntax
│  ├─ Missing CSeq → Add sequential CSeq header
│  ├─ Wrong RTSP version → Use RTSP/1.0
│  └─ CRLF formatting wrong → Ensure \r\n line endings
│
└─ Still failing?
   ├─ Try ONVIF discovery to get the correct RTSP URL
   ├─ Check camera firmware version (older firmware may have stricter parsing)
   └─ Test with a known-working RTSP client as baseline

Reverse proxy: the hidden 400 cause

RTSP through an HTTP reverse proxy is fragile. Proxies designed for HTTP may:

  1. Inject HTTP-specific headers (Host, X-Forwarded-For, User-Agent)
  2. Rewrite the request URI
  3. Buffer and alter the TCP connection behavior
  4. Interfere with RTSP's persistent connection model

Symptoms of proxy interference:

  • Direct RTSP to camera: works
  • RTSP through proxy: 400 Bad Request
  • Camera logs show "malformed request" with extra headers not present in the direct flow

Fix: Either bypass the proxy for RTSP traffic, use an RTSP-aware proxy, or configure the proxy to pass RTSP traffic unmodified.

Authentication edge cases

Most auth problems return 401, but a malformed Authorization header can return 400.

The "works on first try, fails on retry" pattern:

  1. Client sends unauthenticated DESCRIBE
  2. Camera returns 401 with Digest challenge (realm, nonce)
  3. Client computes Digest response
  4. Client sends authenticated DESCRIBE with Authorization header
  5. Camera returns 400

This happens when the Digest response computation is wrong — the URI used in the Digest calculation doesn't match the actual request URI, or the nonce was stale, or special characters in the password weren't encoded correctly before hashing.

Check: Compare the request URI in the Authorization header with the actual request URI on the wire. In Digest auth, the URI is part of the hash — if they don't match character-for-character (including encoding), the response is invalid.

When the camera is just broken

Some cameras have buggy RTSP implementations. If you've checked everything above and still get 400:

  1. Check for firmware updates
  2. Test with the manufacturer's own client software
  3. Try ONVIF as an alternative discovery and streaming path
  4. If the camera works with its own app but not with standards-compliant RTSP clients, the camera's RTSP stack is non-compliant

File a bug with the camera vendor. Include the exact RTSP DESCRIBE request and response. A proper RTSP implementation should not return 400 for a valid, well-formed request regardless of the URL path — it should return 404.