System designHow-to

Embed a live camera feed in a web dashboard

Embed a live camera feed in a web dashboard: find the snapshot or MJPEG URL, fix the HTTPS mixed-content block, and size the refresh rate.

LumaSpec Vision11 min read Share on LinkedIn

On this page 9 sections
  1. 01Snapshot and MJPEG: the two feed URLs
  2. 02Why an HTTP stream blanks out on an HTTPS page
  3. 03What you need
  4. 04Embed the feed, step by step
    1. The three snippets
  5. 05Pick the refresh rate, then check the bandwidth
  6. 06Verify the feed in the browser
  7. 07Common mistakes
  8. 08When a dashboard tile is the wrong tool
  9. 09Questions

Your dashboard already shows the temperatures, counts and alarms. The camera tile is the missing piece: most web dashboards and historian views have no native video widget, and dropping a camera URL into a static image frame gives you either a frozen picture or an empty box. This how-to is for engineers wiring any network camera — an infrared camera watching an oven, a smart camera over a filling line, an area scan camera on a robot cell — into a browser-based dashboard. You will find the camera's snapshot and MJPEG URLs, get them past the browser's HTTPS mixed-content rule, embed them with a few lines of HTML, and size the refresh rate with real arithmetic.

Snapshot and MJPEG: the two feed URLs

A snapshot URL answers every HTTP GET with a single JPEG. To update the picture you request it again — that is the whole protocol, and it makes snapshots the easiest feed to proxy, cache-bust and budget bandwidth for. The pattern is documented end to end in grab images from an IP camera over an HTTP snapshot URL.

An MJPEG stream is one long HTTP response of type multipart/x-mixed-replace. The camera pushes JPEG frame after JPEG frame down that response, and a desktop browser renders it directly inside an img element — no plugin, no player library, no JavaScript. The same stream type is what a client reads in decoding barcodes from a live RTSP or MJPEG video stream.

RTSP is the third protocol many cameras speak, and browsers cannot play it in an img or video element at all, so it always needs a conversion step (the FAQ covers the two routes).

To find your camera's URLs, open its built-in web page, start the browser developer tools and watch the Network tab while the live view plays. The request that repeats is the stream URL; a request that returns one JPEG is the snapshot. File names such as snapshot.jpg or video.mjpeg are common, but never assume — read what your camera actually requests.

Why an HTTP stream blanks out on an HTTPS page

Dashboards are served over HTTPS in any plant that takes security seriously — single sign-on and security policy see to that. The browser then applies the mixed-content rule: a page loaded over HTTPS may not pull subresources over plain HTTP. Current Chrome, Edge and Firefox upgrade an http image URL to https, and block it when the upgrade fails; scripts and iframes from HTTP sources are blocked outright. Since the camera serves no TLS, the request dies and the tile stays empty. The browser's developer console names the blocked request as mixed content, so the diagnosis is one glance away.

The rule that follows: every URL you embed must answer over HTTPS. You have two ways to get there. Enable HTTPS on the camera itself if it offers it, and deal with a self-signed certificate warning on every client. Or keep the camera on plain HTTP and terminate TLS on a reverse proxy on the dashboard server, where you install one trusted certificate for the whole plant. The proxy is the answer in most plants, and it also solves authentication and fan-out, as the steps below show.

What you need

  • A camera that serves a snapshot or MJPEG URL from its own web page — most monitoring and IP cameras do.
  • Any machine-vision camera without a web page: it joins through the relay service in step 4, which needs a host with a GenICam client.
  • A dashboard that accepts custom content: a custom symbol, web part, HTML widget or iframe.
  • A server you control for the proxy or relay — the dashboard host itself is fine, and a fanless industrial mini PC in the control cabinet is the usual carrier.
  • One TLS certificate for that host, issued through your plant's normal certificate process.

For an oven or furnace status tile the source is usually a fixed thermal camera. The LS-IRC-0044 reads the 8-14 μm LWIR band and answers over GigE, so the dashboard host reaches it directly:

Infrared cameras640 x 512 thermal camera, 8-14 μm, 50 Hz, GigE, FOV 88.5° × 73.2°, 9-24 V DC (LS-IRC-0044)LS-IRC-0044
Lens mount
C-mount
Interface
GigE
Resolution
Up to 3 MP
Spectrum
LWIR
$5,885.00 · quotedView and quote

Inspection cameras feed a dashboard the same way — every model below is a GigE camera, so the relay host reaches it over the plant network:

Smart cameras & vision sensorsHikrobot MV-SC5060XM-08M-WBN SC5000X series Smart Camera, 6 MP, Mono, 8 mm focal length, M12-mountMV-SC5060XM-08M-WBN
Interface
GigE
Resolution
6-10 MP
$1,629.00View part
Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
$309.00View part
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

Embed the feed, step by step

Six steps take you from a working camera page to a live dashboard tile.

  1. Find and test both URLs. Open the camera's own web page, start the browser developer tools and watch the Network tab while the live view plays: the request that repeats is the stream URL, and the request that returns one JPEG is the snapshot. Test each URL alone in a browser tab before touching the dashboard.
  2. Decide direct or proxied. If the camera serves HTTPS, embed its URL directly. If it is HTTP-only — the common case — plan the reverse proxy of step 3. There is no third option: the mixed-content rule blocks the plain HTTP URL however you write the HTML.
  3. Configure the reverse proxy. One location per camera under a single certificate on the dashboard host, with basic auth injected server side if the camera asks for a login (snippet A).
  4. Run a relay for cameras without a web page. A GenICam-only camera has no URL to proxy, so the dashboard host runs a small service that grabs frames from the camera, encodes each to JPEG and serves its own snapshot and stream endpoints under the same certificate. The grab loop is the same pattern wired up in live edge detection from a video stream, with an HTTP handler in front. The relay decouples the camera's frame rate from the dashboard's poll rate, which the bandwidth budget below relies on.
  5. Embed the feed with one img tag for MJPEG or a timed poll for the snapshot (snippets B and C).
  6. Set the rate and verify with the budget and checks in the next two sections.

The three snippets

Snippet A — an illustrative nginx fragment; replace the names and addresses with your own:

server {
    listen 443 ssl;
    server_name dash.plant.example;

    location /cam1/ {
        proxy_pass http://10.0.4.21/;
        proxy_buffering off;   # stream frames out as they arrive
    }
    location /cam2/ {
        proxy_pass http://10.0.4.22/;
    }
}

If the camera requires basic auth, add proxy_set_header Authorization "Basic <base64 of user:password>"; to its location. Generate that base64 string yourself from the camera login; never reuse a default, and never place credentials in the dashboard page itself, where anyone can read them in the source.

Snippet B — the documented way to play an MJPEG stream: the img element renders it directly, no script needed.

<img width="640" alt="Oven 2 door"
     src="https://dash.plant.example/cam1/video.mjpeg">

Snippet C — an illustrative 2 Hz snapshot poll; setInterval and Date.now are standard browser APIs, and camUrl is your camera's proxied snapshot URL:

const img = document.getElementById("cam1");   // the img element above
const camUrl = "https://dash.plant.example/cam1/snapshot.jpg";
setInterval(() => {
  img.src = camUrl + "?t=" + Date.now();
}, 500);                                       // 500 ms = 2 Hz

The cache-busting parameter is not decoration: it defeats every cache between browser and proxy, which is the most common reason a snapshot tile shows the same frame forever.

Pick the refresh rate, then check the bandwidth

Set the rate by what the tile is for:

  • Status wall, eight to twenty tiles: 1-2 Hz snapshots.
  • One process tile you watch closely: 5 Hz.
  • A watched camera where motion matters: MJPEG at 10-20 fps.
  • Full camera rate: only in a dedicated operator viewer, never a shared dashboard.
frame size [B] ≈ pixels × bits per pixel / 8 bandwidth [Mbit/s] ≈ frame size [kB] × 8 × rate [Hz] / 1000

Worked example — a ten-camera thermal status wall at 2 Hz:

  1. Frame: the LS-IRC-0044 delivers a 640 × 512 frame. That is 640 × 512 = 327,680 pixels per frame.
  2. Size: a smooth thermal scene at moderate JPEG quality lands near 1.5 bits per pixel, so 327,680 × 1.5 / 8 = 61,440 bytes ≈ 60 kB per frame. Treat 40-80 kB as the realistic band; cluttered scenes compress worse.
  3. Poll at 2 Hz: 60 kB × 8 × 2 = 960 kbit/s ≈ 1 Mbit/s per camera.
  4. Ten cameras: about 10 Mbit/s — comfortable on a 100 Mbit/s link alongside the rest of the plant traffic.
  5. Push the same ten cameras to 10 Hz and each needs 60 × 8 × 10 = 4.8 Mbit/s, so 48 Mbit/s total — half the link gone. Stay at 2 Hz for walls.
  6. One MJPEG stream at 20 fps costs 60 × 8 × 20 = 9.6 Mbit/s per viewer, and the full 50 fps rate is 24 Mbit/s. The proxy pulls the camera once and fans frames out on its own side, so twenty viewers still cost the camera 24 Mbit/s, not 480.

Latency moves with the rate: a 2 Hz snapshot tile shows a scene on average half a poll interval old, plus fetch and render — call it 0.5-1.5 s scene-to-screen as an estimate. Monitoring does not care; if someone needs to time motion off the dashboard, give that tile MJPEG.

The decision, per case: snapshots at 2 Hz for a status wall, 20 fps MJPEG through the proxy for a watched camera, full rate only in a dedicated viewer.

Verify the feed in the browser

  • Console first: no mixed-content errors, which leave a distinct console message.
  • Network tab: a snapshot request every 500 ms with status 200 and type image/jpeg, or one long request of type multipart/x-mixed-replace for a stream.
  • Freshness test: cover the lens with your hand. The tile must change within one poll interval. If it does not, a cache is serving stale frames — keep the cache-buster and confirm caching is off for the camera location.
  • Fan-out test: open the dashboard on a second machine and confirm the camera-side request rate did not multiply. The proxy should still hold one connection per camera.
  • Latency check: point the camera at a wall clock and compare. About 0.5-1.5 s for a 2 Hz snapshot tile is normal; more means a queue, usually polling faster than the camera's snapshot service answers.

Common mistakes

  • An RTSP URL pasted into an img tag: nothing renders, because browsers have no RTSP. Convert the stream first (the FAQ gives the two routes).
  • Polling faster than the camera's snapshot service answers: timeouts, gaps, sometimes a camera that stops responding to everything. Stay at 5 Hz or below unless the camera's documentation allows more.
  • One stream per viewer at full rate: the camera uplink saturates long before the dashboard looks slow — one 50 fps stream is 24 Mbit/s by the arithmetic above. Pull once, fan out.
  • Credentials in the page: browsers drop user:password URLs, and anything in the page source is readable by every dashboard user. Keep authentication in the proxy.
  • A dashboard tile standing in for a safety view:

When a dashboard tile is the wrong tool

A 2 Hz tile answers "is the oven lit", not "show me the cycle". When operators need continuous video, put the stream where they already work: an HMI viewer widget (show a camera live stream in an HMI web viewer widget), the line's own web HMI (embed a machine vision camera stream in a web HMI), or the SCADA window the cell already runs (embed an IP camera stream in an HMI or SCADA window). If the feed belongs beside the trend charts permanently, streaming smart camera video and metrics to a custom dashboard covers the metrics side of that build. And for one person's quick look from a desk, a one-button live view over the snapshot URL (remote IP camera snapshot URL for a one-button live view) beats wiring a tile at all.

To pick the camera side of the feed, filter by interface and resolution in the camera finder, or start here:

Build the whole station

The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.

Start with the camera

If the dashboard side is fixed and you want a check on the camera choice, the contact page reaches the applications team.

Questions

Can I embed an HTTP camera stream in an HTTPS dashboard?

Not directly. Browsers treat HTTP subresources on an HTTPS page as mixed content: image URLs get upgraded to HTTPS and blocked when the camera serves no TLS, so the tile stays empty. Terminate TLS on a reverse proxy in front of the camera and embed the proxy's HTTPS URL. If the camera itself offers HTTPS, embed its URL directly, accepting certificate warnings unless you install a trusted cert.

What refresh rate should a dashboard camera feed run at?

Poll snapshots at 1-2 Hz for a status wall and 5 Hz for a process tile you watch closely. A watched camera justifies an MJPEG stream at 10-20 fps; full camera rate belongs in a dedicated viewer, not a shared dashboard. Every doubling of the rate doubles the bandwidth: a 60 kB frame at 2 Hz costs about 1 Mbit/s per camera.

How much bandwidth does one dashboard camera feed use?

Frame size × 8 × rate. A 640 × 512 JPEG of a smooth thermal scene runs about 60 kB, so 2 Hz polling costs 60 × 8 × 2 ≈ 1 Mbit/s per camera, and ten cameras at 2 Hz fit in roughly 10 Mbit/s. The same frame as MJPEG at 20 fps is 9.6 Mbit/s per viewer, and 50 fps reaches 24 Mbit/s — unless a proxy pulls once and fans out.

Why does the camera tile stay broken when the camera page asks for a password?

The snapshot URL needs basic-auth credentials, and an img element cannot send them: browsers no longer accept user:password inside URLs, and page code cannot set headers on image requests. Add the Authorization header on the server side, in the reverse proxy, and keep credentials out of the dashboard page, where every user could read them in the source.

Can I put an RTSP stream straight into a web dashboard?

No. Browsers cannot play RTSP in an img or video element. Either run a gateway that converts the stream to MJPEG, HLS or WebRTC, or grab the RTSP stream in a small host service and re-serve it as an HTTPS MJPEG URL, the same way the relay handles GenICam-only cameras. The dashboard then embeds the converted HTTPS URL as usual.

Do I need a special camera to feed a web dashboard?

No. Any camera that serves a snapshot or MJPEG URL from its own web page works once HTTPS is handled. Machine-vision cameras that only speak GigE Vision work through a relay service on the dashboard host, and USB3-only cameras need the same relay because they have no network address. Choose the camera for the image job — resolution, spectrum, frame rate — then route the feed.