System designTroubleshooting

MJPEG stream URL with username and password: make it play

Your MJPEG stream URL plays in a browser but the player rejects it. Pass the username and password with the URL, percent-encode them and test in VLC.

LumaSpec Vision11 min read Share on LinkedIn

On this page 10 sections
  1. 01Symptom: the browser plays it, the player calls the file invalid
  2. 02Rank the causes before you touch anything
  3. 03Why a browser succeeds where a player fails
  4. 04The fix: carry the login inside the URL
  5. 05Encode the characters that break the URL
  6. 06Prove the URL on the bench in five minutes
  7. 07When the login is right and the player still refuses
  8. 08Set the feed up so the fault cannot return
  9. 09Hand-over checklist
  10. 10Questions

The MJPEG address opens in your browser and the live image is right there. Paste the same URL into a video player component on an HMI, SCADA screen or dashboard and it fails with an error such as 'Error Loading Media: File not valid'. The camera and the network are almost never the problem. The camera is asking for a username and password; the browser answers with a login box, while the player has nobody to type one in. This guide gives you the fix first — the login carried inside the stream URL — then the encoding rules that keep special characters from breaking it, a bench test that proves the exact address, and the set-up choices that stop the fault from coming back.

Symptom: the browser plays it, the player calls the file invalid

The signature is specific: one URL, two different results. In a browser the camera shows its login prompt once, then streams. In the player component the same address produces an error in seconds and no picture at all.

That error means the player received bytes it cannot render. In almost every case those bytes are the camera's login error page — not a broken camera and not a corrupt stream. The player downloads, gets an HTML error page instead of multipart JPEG data, and reports the source as an invalid file.

Two checks separate the causes. If the browser asks for a login before playing, the credentials are the problem: carry them in the URL as shown below. If the browser plays with no prompt, the login is already cached and you are looking at a rendering or scheme fault instead. SCADA platforms add settings of their own around this fault; the SCADA IP camera MJPEG stream configuration troubleshooting page covers that layer.

If you have not yet confirmed the path itself, start with MJPEG viewer shows no video: point the URL at the real stream. This guide assumes the path is right and fixes the login.

Rank the causes before you touch anything

Cause Why it fits Test Fix
Credentials missing Browser prompts, player cannot The curl test returns 401 Login inside the URL, next section
Digest-only camera, basic-only player A browser answers either scheme Response header shows a digest challenge Enable basic on a restricted account, or use a player that answers digest
Player cannot render multipart MJPEG VLC plays, the player does not Compare against VLC with the same URL Snapshot polling or an RTSP URL
Scheme or port mismatch The browser bar shows https:// or a :port Compare the working address field by field Match scheme and port in the source
Bandwidth or client limit Works alone, fails with other viewers open Close the other clients and retry Lower frame rate or resolution, spread cameras out

The first row explains most cases where the browser plays and the player does not. Rows two to four matter after the credentials go in; row five shows up weeks later on a loaded network.

Why a browser succeeds where a player fails

The camera protects its stream with HTTP authentication. A request without a login gets the status 401 Unauthorized plus a header naming the scheme the camera wants, normally basic or digest. A browser intercepts that reply, opens its username-and-password dialog, and replays the request with an Authorization header. You see one prompt, then video.

An embedded player has no dialog to open. Minimal viewers frequently implement none of the challenge, and many that do implement only the basic scheme. Their request stops at the 401, the only bytes they receive are the camera's error page, and 'file not valid' is how that dead end looks from the screen.

A third variant leaves the URL powerless altogether: some cameras guard everything behind a login form that sets a session cookie. No URL can carry that login; you need an integration endpoint or a client of your own, covered near the end of this guide.

The fix: carry the login inside the URL

http://username:password@host:port/path

The login goes before the at-sign, the camera address after it, in that order. The examples use 192.168.1.50 as the camera address and /mjpg/video.cgi as a stand-in path; take the real path from your camera's integration manual and keep the address form shown here.

Worked example. Camera at 192.168.1.50, MJPEG service on port 80, account viewer with the password P@ss w0rd!. The password contains @, a space and !, which encode as %40, %20 and %21. Build the final source from its parts, in this order: the scheme, the username, a colon, the encoded password, an at-sign, the address, then the path:

http:// + viewer + : + P%40ss%20w0rd%21 + @ + 192.168.1.50 + /mjpg/video.cgi

Joined with no spaces, that is the complete source your player takes. With a password that avoids special characters, such as Read0nly1, the same recipe needs no encoding at all: scheme, viewer, colon, Read0nly1, at-sign, address, path.

If the service runs on port 8080, the port goes after the address with a second colon, before the path: keep the parts above and insert : + 8080 between the address and the path.

If your HMI runs one of the platform-specific camera viewer components, the same URL goes in its source field; resolving Ignition IP camera viewer URL and stream errors covers that component's settings.

Encode the characters that break the URL

The URI standard, RFC 3986, reserves a set of characters for URL structure, and inside a username or password each one needs its percent-encoded form:

Character Write it as
space %20
! %21
quotation mark %22
# %23
% %25
/ %2F
: %3A
? %3F
@ %40
[ %5B
] %5D

Two rules keep the encoding honest. The single colon that separates username from password stays literal: encode the colons inside the values, never the separator. Letters outside the ASCII set are written as their UTF-8 bytes. When in doubt, encode — an unnecessary %40 decodes harmlessly at the camera, while one bare @ inside a password truncates the username and fails the login with no visible reason.

Prove the URL on the bench in five minutes

  1. Build the final URL in a text editor and open it in a browser. It must play with no prompt. A prompt means the encoding or the credentials are wrong — fix it here, not on the screen.
  2. Check the status code from a non-browser client: curl -s -D headers.txt -o frame.jpg --user viewer:'P@ss w0rd!' http://192.168.1.50/mjpg/video.cgi. headers.txt starts with HTTP/1.1 200 OK when the server accepts the login without a dialog, and frame.jpg holds a still from the stream. A 401 there means scheme or credentials.
  3. On a 401, see which scheme the camera demands: curl -v --anyauth --user viewer:Read0nly1 -o frame.jpg http://192.168.1.50/mjpg/video.cgi 2> trace.txt. The trace shows the WWW-Authenticate challenge and the response curl negotiated. A camera that insists on digest will keep failing a basic-only player even with correct credentials in the URL.
  4. Open a network stream in VLC and paste the exact URL. VLC-based and ffmpeg-based engines answer either scheme, so a picture here clears both the login and the rendering for those clients.
  5. Only now paste the URL into the player component. If steps 1 to 4 pass and the component still refuses, the cause is rendering, not the login — next section.

When the login is right and the player still refuses

Three faults survive correct credentials, in this order.

The player cannot render multipart MJPEG. A moving MJPEG stream arrives as multipart/x-mixed-replace, a content type a browser renders on a page but most lightweight HTML5 video components reject. If the screen needs an update every second or two, switch the component to snapshot mode and drive it with HTTP snapshot URL polling: IP camera still image on a timer, or use a viewer widget that documents MJPEG support, such as the one in show a camera live stream in an HMI web viewer widget. Where the camera offers RTSP, that is the wider road: display an RTSP camera stream in an HMI: snapshot URL or VLC.

The camera insists on digest. Enable basic authentication as well, on the read-only account, and keep that URL inside the restricted network. Players with full digest support are the other way out.

The camera is HTTPS-only. Write https:// and the port in the source. A self-signed certificate is refused by many players, so the clean options are a properly signed certificate or plain HTTP kept inside the restricted network.

Bandwidth and client limits come last, and they surface weeks after commissioning. A 1280 × 720 stream at 15 fps with an assumed 60 KB per JPEG frame moves 60,000 × 15 = 900,000 bytes per second, which is 900,000 × 8 = 7.2 Mbit/s per viewer. Four viewers put 28.8 Mbit/s on one run, well inside a 100 Mbit/s link but enough that entry-level cameras, which commonly cap simultaneous HTTP clients in the single digits, start refusing connections. Give wall displays a slower snapshot; keep the full-rate stream for the inspection client.

Set the feed up so the fault cannot return

A camera bought for this job should hand you the URL and the account, not a puzzle. The three below stream over Fast Ethernet with an account you set in their own interface: a 1.6 MP color check, a 5 MP detail check and a mono presence check.

Smart cameras & vision sensorsHikrobot MV-SCB007EC-12S-WBN SCB vision sensor, 1.6 MP, Color, 12 mm lens, Manual focusMV-SCB007EC-12S-WBN
Interface
Fast Ethernet
Resolution
Up to 3 MP
$1,989.00 · quotedView and quote
Smart cameras & vision sensorsHikrobot MV-SC3050XC-16M-ATN-H 5 MP color vision sensorMV-SC3050XC-16M-ATN-H
Interface
Fast Ethernet
Resolution
5 MP
$1,809.00View part
Smart cameras & vision sensorsHikrobot HK-TD032-12-WBN 1.6 MP mono vision sensorHK-TD032-12-WBN
Interface
Fast Ethernet
Resolution
Up to 3 MP
$1,699.00View part

For a self-contained stream node, the LS-SMC-0063 pairs a 1.6 MP sensor with a 16 mm lens, built-in white light and 60 fps over GigE.

Smart cameras & vision sensors1.6 MP smart camera, 60 fps, 16 mm lens, white light (polarized, transparent light) (LS-SMC-0063)LS-SMC-0063
Interface
GigE
Resolution
Up to 3 MP
$1,110.00View part

Browse the wider ranges in smart cameras and area scan cameras, or filter by interface, resolution and shutter in the camera finder.

Hand-over checklist

  • Final URL plays in a browser with no prompt — proves credentials and encoding.
  • The curl test returns HTTP/1.1 200 OK — proves the server accepts the login from a non-browser client.
  • VLC plays the exact URL — proves a non-browser renderer handles the stream.
  • Separator colon literal, every other special character encoded — one bare @ silently truncates the login.
  • Read-only account on a restricted network — the URL is plain text wherever it is stored.
  • Every final URL written next to the panel drawings — the next password change takes minutes.

If the bench test passes and the screen still refuses the feed, send us the camera model and the exact URL through the contact page — free expert support comes with every order, and reading camera integration manuals is a large part of that job. To pick the camera side of a new line, start in the camera configurator, and keep the wider stream debugging under the systems topic.

Questions

Is it safe to put a password in an MJPEG stream URL?

Over HTTP the URL travels as plain text, and it sits in browser history, player logs and configuration exports. Reduce the exposure instead of accepting it: a read-only account that can fetch images and nothing else, a camera on a restricted network segment, HTTPS if the camera carries a proper certificate, and a scheduled password rotation where you regenerate every URL from your documentation file in one pass.

Does the username:password form work with digest authentication?

Usually with full players, not always with minimal ones. Engines built on VLC or ffmpeg take the credentials from the URL and answer either a basic or a digest challenge; browsers do the same once you have typed the login. Minimal viewers frequently implement only basic, so on a digest-only camera their URL credentials are ignored. The curl --anyauth test shows which scheme the camera demands before you blame the player.

What if the camera uses a login form and a session cookie instead of HTTP authentication?

Then no URL can carry the login, because the camera hands out a cookie after a form post rather than issuing a 401 challenge. Use an endpoint designed for integration, such as a snapshot or CGI URL that takes credentials as parameters, or write a small client that logs in once, keeps the cookie and saves frames on a timer. Both patterns are simpler than they sound.

How many viewers can watch one camera stream at the same time?

Entry-level network cameras commonly cap concurrent HTTP clients in the single digits. The bandwidth math sets a second ceiling: a 640 × 480 stream at 10 fps with an assumed 40 KB per frame moves 40,000 × 10 × 8 = 3.2 Mbit/s per viewer, so six viewers already put about 19 Mbit/s on one camera's uplink. Count screens before deployment and give wall displays a slower polling snapshot instead of a full stream.

The URL plays in VLC but the player component still shows the error. What is left?

The login is solved; the remaining gap is rendering. VLC speaks multipart/x-mixed-replace and many lightweight HTML5-based components do not. Check which content types and protocols the component documents, switch the component to snapshot or image mode with polling if MJPEG is missing, or feed it an RTSP URL, which far more players accept natively. A component that accepts neither belongs to the platform's own viewer widget instead.