<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Super Funicular</title>
    <description>The latest articles on DEV Community by Super Funicular (@superfunicular).</description>
    <link>https://dev.to/superfunicular</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3905292%2F0eab2966-f7d2-41d0-983d-d240a6caa5d4.jpg</url>
      <title>DEV Community: Super Funicular</title>
      <link>https://dev.to/superfunicular</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/superfunicular"/>
    <language>en</language>
    <item>
      <title>What Happens to a Phone's YouTube Live Stream When Mobile Data Drops? enableAutoStop, Stream Health, and the One-Minute Window</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Mon, 12 Oct 2026 07:14:43 +0000</pubDate>
      <link>https://dev.to/superfunicular/what-happens-to-a-phones-youtube-live-stream-when-mobile-data-drops-enableautostop-stream-3556</link>
      <guid>https://dev.to/superfunicular/what-happens-to-a-phones-youtube-live-stream-when-mobile-data-drops-enableautostop-stream-3556</guid>
      <description>&lt;p&gt;If you stream a phone camera to YouTube Live over mobile data, the connection will drop at some point. A train goes past, the tower gets busy, the prepaid pack runs out, the power cuts and the router goes down with it. The phone usually reconnects within seconds or minutes.&lt;/p&gt;

&lt;p&gt;The question this piece answers is narrower and more useful: &lt;strong&gt;what does YouTube do with your broadcast during that gap, and what decides whether you come back to the same live video or a new one?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything below comes from Google's own YouTube Live API reference and YouTube Help pages, quoted directly and linked at the end. Where the docs say nothing, I say that too, because a few of the answers people repeat on forums are not in any Google document.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens to a YouTube Live stream when the phone's data drops?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Short answer: YouTube stops receiving video, the stream is reported as inactive, and viewers see buffering. If the broadcast has auto-stop turned on, YouTube ends it "around one minute" after video stops arriving. After that, the live video is finished and a reconnect needs a new broadcast.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether a reconnect &lt;em&gt;inside&lt;/em&gt; that minute continues the same broadcast is not documented by Google. Test it on your own channel before you rely on it (a 10-minute test is at the end).&lt;/p&gt;

&lt;p&gt;If you use &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w42" rel="noopener noreferrer"&gt;Background Camera RemoteStream&lt;/a&gt;: it records with the screen off to the phone's own storage, serves a live view to browsers on your own Wi-Fi, and can push to YouTube Live when you want to watch from outside. No account with us, no cloud of ours, no subscription. The YouTube behaviour below is YouTube's, and it applies to any app or encoder that streams to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two objects, not one: the broadcast and the stream
&lt;/h2&gt;

&lt;p&gt;Most confusion about drops comes from treating "the stream" as one thing. The YouTube Live API splits it in two, and we walked through how an app creates both in &lt;a href="https://dev.to/superfunicular/streaming-to-youtube-live-from-an-android-phone-with-the-screen-off-the-whole-path-end-to-end-ik2"&gt;Streaming to YouTube Live From an Android Phone With the Screen Off&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;liveStream&lt;/strong&gt; is the pipe. It holds the ingest address and the stream key. Your phone pushes video into it.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;liveBroadcast&lt;/strong&gt; is the event viewers watch. It has a watch page, a privacy setting and, later, an archive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The broadcast is &lt;em&gt;bound&lt;/em&gt; to a stream. When the data drops, the pipe goes quiet. What happens to the event depends on settings on the broadcast.&lt;/p&gt;

&lt;p&gt;The pipe usually survives. Google's reference for the &lt;code&gt;isReusable&lt;/code&gt; property says a reusable stream "can be bound to multiple broadcasts. It is common for broadcasters to reuse the same stream for many different broadcasts if those broadcasts occur at different times." The broadcast guide says streams are reusable by default: "you can just reuse the stream ID for subsequent broadcasts."&lt;/p&gt;

&lt;p&gt;So a drop does &lt;strong&gt;not&lt;/strong&gt; mean you need a new stream key. It may mean you need a new broadcast.&lt;/p&gt;

&lt;h2&gt;
  
  
  What YouTube reports while the data is gone
&lt;/h2&gt;

&lt;p&gt;The liveStream resource has a &lt;code&gt;status.streamStatus&lt;/code&gt; field. Its documented values are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Google's description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;active&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"The stream is in active state which means the user is receiving data via the stream."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;inactive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"The stream is in inactive state which means the user is not receiving data via the stream."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ready&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"The stream has valid CDN settings."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;created&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The stream "does not have valid CDN settings."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"An error condition exists on the stream."&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A dropped phone is the &lt;code&gt;active&lt;/code&gt; to &lt;code&gt;inactive&lt;/code&gt; case. Nothing in that list is "reconnecting".&lt;/p&gt;

&lt;p&gt;There is also &lt;code&gt;status.healthStatus.status&lt;/code&gt;, with four values: &lt;code&gt;good&lt;/code&gt;, &lt;code&gt;ok&lt;/code&gt;, &lt;code&gt;bad&lt;/code&gt;, and &lt;code&gt;noData&lt;/code&gt;, which Google describes as "YouTube's live streaming backend servers do not have any information about the stream's health status."&lt;/p&gt;

&lt;p&gt;One thing I expected to be documented and is not: &lt;strong&gt;which health value you see during a gap&lt;/strong&gt;. It would be easy to write "health turns red". No Google page says that. What the docs do give is a specific health issue for a weak connection, &lt;code&gt;videoIngestionStarved&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"YouTube is not receiving enough video to maintain smooth streaming. As such, viewers will experience buffering."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the documented viewer experience of a starving stream: &lt;strong&gt;buffering&lt;/strong&gt;. I could not find any Google text promising an "offline" card, a frozen last frame, or a slate. If you have seen one, that is observed behaviour, not a documented contract, and it may change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setting that decides it: enableAutoStop
&lt;/h2&gt;

&lt;p&gt;The broadcast resource has a property called &lt;code&gt;contentDetails.enableAutoStop&lt;/code&gt;. Google's reference describes it in one sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Indicates whether this broadcast should stop automatically around one minute after the channel owner stops streaming video on the bound video stream."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The broadcast lifecycle guide says the same thing from the other side: "YouTube will automatically end the broadcast around a minute after you stop sending video on the bound live stream."&lt;/p&gt;

&lt;p&gt;Note the wording: &lt;strong&gt;"around one minute"&lt;/strong&gt;. Not 60 seconds exactly, and not a promise. Build in margin.&lt;/p&gt;

&lt;p&gt;From YouTube's point of view, a phone that loses data and a person who deliberately stops streaming look the same. Both stop sending video. YouTube's own "Stream now" instructions say: "To end the stream, stop sending content from your encoder." That is fine for someone who means to stop. On mobile data, a dead zone does the same thing.&lt;/p&gt;

&lt;p&gt;Once the broadcast ends, its &lt;code&gt;lifeCycleStatus&lt;/code&gt; becomes &lt;code&gt;complete&lt;/code&gt;, which the transition reference describes as "The broadcast is over. YouTube stops transmitting video." Moving a broadcast to &lt;code&gt;live&lt;/code&gt; requires the stream to be &lt;code&gt;active&lt;/code&gt;, and asking for a move YouTube does not allow returns an &lt;code&gt;invalidTransition&lt;/code&gt; error. No Google page says in so many words "a complete broadcast can never go live again". But nothing documents a way back, and the safe plan is: &lt;strong&gt;after &lt;code&gt;complete&lt;/code&gt;, a reconnect means a new broadcast, with a new watch URL.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That last part matters more than it sounds. If you sent a family member the link to watch the shop overnight, and the link pointed at a broadcast that auto-stopped at 2:14 a.m., that link now shows a finished video. The camera may be streaming again at 2:16 to a different URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about enableAutoStart?
&lt;/h3&gt;

&lt;p&gt;Its pair, &lt;code&gt;enableAutoStart&lt;/code&gt;, "Indicates whether this broadcast should start automatically when you start streaming video on the bound live stream." The lifecycle guide gives its default as false. For &lt;code&gt;enableAutoStop&lt;/code&gt;, the current reference documents &lt;strong&gt;no default&lt;/strong&gt;, so check the value your app or encoder actually sets rather than assuming one.&lt;/p&gt;

&lt;p&gt;Two more details from the docs, for anyone writing their own integration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Per the lifecycle guide, auto-start and auto-stop "can't be set to true before the testing stage because the test would actually cause the broadcast to start."&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enableAutoStop&lt;/code&gt; is listed as updatable. The exception is persistent broadcasts, where the &lt;code&gt;invalidAutoStop&lt;/code&gt; error reads: "You cannot modify the enableAutoStop setting for a persistent broadcast."&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Turn auto-stop off, then? Not so fast
&lt;/h2&gt;

&lt;p&gt;If auto-stop ends broadcasts on every short drop, the obvious move is to switch it off. Then the broadcast stays in &lt;code&gt;live&lt;/code&gt; while the pipe is &lt;code&gt;inactive&lt;/code&gt;, and when the phone comes back the same event can carry on.&lt;/p&gt;

&lt;p&gt;The cost is the other side of the same coin: &lt;strong&gt;if the phone never comes back&lt;/strong&gt; (flat battery, a power cut that outlasts the backup, a prepaid pack that ran out at midnight), the broadcast stays "live" with nothing in it until someone ends it. For a camera nobody is watching, that is mostly harmless clutter. For a channel with subscribers, it is a live event showing buffering.&lt;/p&gt;

&lt;p&gt;There is no right answer here. There is a choice that matches how your connection fails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Short, frequent drops&lt;/strong&gt; (moving vehicles, a weak signal at the edge of a tower, a busy cell in the evening): auto-stop &lt;strong&gt;off&lt;/strong&gt; keeps one link working. Plan to end broadcasts yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long or final drops&lt;/strong&gt; (power cuts, data packs running out, a phone left on a shelf for days): auto-stop &lt;strong&gt;on&lt;/strong&gt; cleans up after itself. Accept that each reconnect is a new URL, and that anyone watching will need the new link.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We covered the power-versus-internet split in more detail in &lt;a href="https://dev.to/superfunicular/what-happens-to-a-phone-security-camera-during-a-power-cut-or-an-internet-outage-they-are-not-the-40o5"&gt;What Happens to a Phone Security Camera During a Power Cut or an Internet Outage?&lt;/a&gt;. The short version applies here: an internet outage and a power outage break different things, and a live stream needs both.&lt;/p&gt;

&lt;h2&gt;
  
  
  DVR: what viewers can do after a gap
&lt;/h2&gt;

&lt;p&gt;One related setting is worth knowing. &lt;code&gt;enableDvr&lt;/code&gt; "determines whether viewers can access DVR controls while watching the video", and Google says "The default value for this property is true." The Help Center puts it plainly: "Enabling DVR lets viewers pause, rewind, and continue during your stream."&lt;/p&gt;

&lt;p&gt;For a camera stream, that means someone who opens the link late can scrub back a bit instead of only seeing "now". The reference also says the property "cannot be updated once the broadcast is in the testing or live state", so it is fixed before the stream starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bitrate: make drops less likely in the first place
&lt;/h2&gt;

&lt;p&gt;Many "drops" on mobile data are not total disconnects. The link gets too thin to carry the bitrate you asked for, and YouTube reports the stream as starved. YouTube's encoder settings page gives these H.264 figures:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;720p, 30 fps&lt;/td&gt;
&lt;td&gt;3 Mbps&lt;/td&gt;
&lt;td&gt;8 Mbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;480p, 30 fps&lt;/td&gt;
&lt;td&gt;0.4 Mbps&lt;/td&gt;
&lt;td&gt;4 Mbps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The gap between 720p and 480p minimums is large. On a weak or shared mobile connection, 480p sits much further inside what the link can hold. A &lt;code&gt;bitrateLow&lt;/code&gt; health issue exists precisely for streams running under the recommended rate. If you see it often, dropping resolution is usually worth more than any reconnect setting.&lt;/p&gt;

&lt;p&gt;The data side of this, including what a day of streaming costs on a prepaid pack, is in &lt;a href="https://dev.to/superfunicular/should-you-leave-the-sim-card-in-an-old-phone-security-camera-a-dual-sim-guide-for-offline-wi-fi-587c"&gt;Should You Leave the SIM Card in an Old Phone Security Camera?&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The live stream is a view. The local file is the record.
&lt;/h2&gt;

&lt;p&gt;A YouTube Live broadcast is a way to &lt;em&gt;watch&lt;/em&gt;. It was never a good way to &lt;em&gt;keep&lt;/em&gt; footage from a connection that drops. Anything that happened during a gap simply was not sent.&lt;/p&gt;

&lt;p&gt;That is why a local recording on the phone matters more than any YouTube setting. It does not care whether the mobile network is up. Whether one phone can record to storage and stream at the same time depends on its camera hardware level. We explained how to check yours in &lt;a href="https://dev.to/superfunicular/one-camera-two-consumers-why-recording-and-live-streaming-at-the-same-time-depends-on-your-14i1"&gt;One Camera, Two Consumers&lt;/a&gt;. Keeping recording running with the screen off is its own problem, covered in &lt;a href="https://dev.to/superfunicular/why-does-my-android-camera-stop-recording-when-the-screen-turns-off-doze-workmanager-and-the-1a5d"&gt;Why Does My Android Camera Stop Recording When the Screen Turns Off?&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A 10-minute test you can run today
&lt;/h2&gt;

&lt;p&gt;Docs tell you what YouTube promises. A test tells you what your setup does. Use an &lt;strong&gt;unlisted&lt;/strong&gt; broadcast so nobody else sees it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start a stream from the phone to YouTube and open YouTube Studio's live control room on another device.&lt;/li&gt;
&lt;li&gt;Let it run for two minutes. Note the watch URL.&lt;/li&gt;
&lt;li&gt;Turn on airplane mode on the phone for &lt;strong&gt;20 seconds&lt;/strong&gt;, then turn it off. Watch what the control room shows, and whether the same watch URL picks up again.&lt;/li&gt;
&lt;li&gt;Do it again for &lt;strong&gt;3 minutes&lt;/strong&gt;. Check whether the broadcast has ended and whether a reconnect created a new one.&lt;/li&gt;
&lt;li&gt;Write down both results. That is your real reconnect window, on your phone, your app and your network.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the 20-second gap continues the same broadcast and the 3-minute gap does not, your setup is behaving the way the documented &lt;code&gt;enableAutoStop&lt;/code&gt; description predicts. If both continue, auto-stop is probably off. If both end, something besides auto-stop is closing the session, and it is worth checking your app's own reconnect behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A dropped phone moves the YouTube &lt;strong&gt;stream&lt;/strong&gt; from &lt;code&gt;active&lt;/code&gt; to &lt;code&gt;inactive&lt;/code&gt;. The stream key survives; reusable streams are the documented default.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;broadcast&lt;/strong&gt; is what can end. With &lt;code&gt;enableAutoStop&lt;/code&gt; on, YouTube ends it "around one minute" after video stops arriving.&lt;/li&gt;
&lt;li&gt;After a broadcast is &lt;code&gt;complete&lt;/code&gt;, plan on a new broadcast and a new watch URL.&lt;/li&gt;
&lt;li&gt;The documented viewer experience of a starved stream is &lt;strong&gt;buffering&lt;/strong&gt;. Nothing in Google's docs promises an "offline" screen.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enableAutoStop&lt;/code&gt; has no documented default. Check what your app sets.&lt;/li&gt;
&lt;li&gt;Lower bitrate prevents many drops. A local recording covers the ones you cannot prevent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get the app on &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w42" rel="noopener noreferrer"&gt;Google Play&lt;/a&gt; or read more at &lt;a href="https://superfunicular.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w42" rel="noopener noreferrer"&gt;superfunicular.com&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Sources
&lt;/h3&gt;

&lt;p&gt;All pages read on 12 October 2026.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/youtube/v3/live/docs/liveBroadcasts" rel="noopener noreferrer"&gt;YouTube Live Streaming API: LiveBroadcasts resource&lt;/a&gt;: &lt;code&gt;enableAutoStop&lt;/code&gt;, &lt;code&gt;enableAutoStart&lt;/code&gt;, &lt;code&gt;enableDvr&lt;/code&gt;, &lt;code&gt;lifeCycleStatus&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/youtube/v3/live/life-of-a-broadcast" rel="noopener noreferrer"&gt;YouTube Live Streaming API: Life of a Broadcast&lt;/a&gt;: auto-stop "around a minute", auto-start default, testing-stage restriction, stream reuse&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/transition" rel="noopener noreferrer"&gt;LiveBroadcasts: transition&lt;/a&gt;: &lt;code&gt;complete&lt;/code&gt;, &lt;code&gt;invalidTransition&lt;/code&gt;, &lt;code&gt;active&lt;/code&gt; requirement&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/youtube/v3/live/docs/liveBroadcasts/update" rel="noopener noreferrer"&gt;LiveBroadcasts: update&lt;/a&gt;: &lt;code&gt;invalidAutoStop&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/youtube/v3/live/docs/liveStreams" rel="noopener noreferrer"&gt;YouTube Live Streaming API: LiveStreams resource&lt;/a&gt;: &lt;code&gt;streamStatus&lt;/code&gt;, &lt;code&gt;healthStatus&lt;/code&gt;, &lt;code&gt;isReusable&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/youtube/v3/live/docs/liveStreams/health_status_messages" rel="noopener noreferrer"&gt;Live stream health status messages&lt;/a&gt;: &lt;code&gt;videoIngestionStarved&lt;/code&gt;, &lt;code&gt;bitrateLow&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.google.com/youtube/answer/2853702" rel="noopener noreferrer"&gt;YouTube Help: Choose live encoder settings, bitrates, and resolutions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.google.com/youtube/answer/2907883" rel="noopener noreferrer"&gt;YouTube Help: Create a live stream with an encoder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.google.com/youtube/answer/9854503" rel="noopener noreferrer"&gt;YouTube Help: Live stream settings (DVR, auto-start and auto-stop)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>youtube</category>
      <category>streaming</category>
      <category>mobile</category>
    </item>
    <item>
      <title>The Camera-Trap Data Standard Starts With When the Camera Was Running, Not What It Saw</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Mon, 12 Oct 2026 05:07:18 +0000</pubDate>
      <link>https://dev.to/superfunicular/the-camera-trap-data-standard-starts-with-when-the-camera-was-running-not-what-it-saw-3gap</link>
      <guid>https://dev.to/superfunicular/the-camera-trap-data-standard-starts-with-when-the-camera-was-running-not-what-it-saw-3gap</guid>
      <description>&lt;p&gt;Three raccoon visits in a week reads like a fact about raccoons. It is at least as much a fact about the camera: how many of those nights it was running, how far out it could make out movement, and whether the clock stamping each clip was right. Wildlife researchers who leave cameras out unattended share a data format that makes them write those things down, and it gives them a table of their own, ahead of anything the camera saw.&lt;/p&gt;

&lt;p&gt;The format is Camtrap DP, maintained by the Camtrap DP Development Team under Biodiversity Information Standards (TDWG). I read its data specification and its FAQ for this piece. I build a camera app for old Android phones and I am not an ecologist, so nothing here is a survey method. What the standard offers a person with a phone pointed at a yard, a feeder or the gap under a fence is a checklist: what to record so that a count can later be read as a rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three tables, and the first one describes the camera
&lt;/h2&gt;

&lt;p&gt;The specification opens its data section plainly: "Data in Camtrap DP are organized as three related resources (CSV files): &lt;code&gt;deployments&lt;/code&gt;, &lt;code&gt;media&lt;/code&gt; and &lt;code&gt;observations&lt;/code&gt;."&lt;/p&gt;

&lt;p&gt;Media is the files. Observations are what a person, or a model, decided was in them. Deployments are the camera's own record: where it was, how it was set up, and for how long. Every media file and every observation carries a &lt;code&gt;deploymentID&lt;/code&gt; that points back to that first table, so nothing the camera recorded can drift loose from the window it was recorded in.&lt;/p&gt;

&lt;p&gt;Of the required fields in the deployments table, two are about time. The start is defined as "Date and time at which the deployment was started. Formatted as an ISO 8601 string with timezone designator", and the end gets the matching definition.&lt;/p&gt;

&lt;p&gt;The timezone part deserves a pause. A clip stamped with a bare date and time names a moment only if you know which clock produced it. With a UTC offset attached it names one instant anywhere. A phone that crossed a time zone, or a folder of clips copied to a computer set to a different zone, is how a naive timestamp quietly moves by hours, and nothing in the file announces it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fields that describe what the camera could see
&lt;/h2&gt;

&lt;p&gt;Beyond time, the deployments table has room for the physical setup. Among them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cameraHeight&lt;/code&gt;, in meters.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cameraTilt&lt;/code&gt;, in degrees, from facing straight down to facing straight up.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cameraHeading&lt;/code&gt;, in degrees clockwise from north.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;detectionDistance&lt;/code&gt;, defined as "Maximum distance at which the camera can reliably detect activity. Expressed in meters. Typically measured by having a human move in front of the camera."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last definition is a procedure, and it is the most useful sentence in the document for anyone mounting a phone. Have someone walk across the frame at increasing distances, then open the recording and find the furthest point at which you can still tell that a body went past. For a phone that records continuously rather than on a trigger, that is my working reading of "detect": the reviewer can see it. Do the walk once in daylight and once after dark, because the answer changes with the light, and write down both.&lt;/p&gt;

&lt;p&gt;A second field matters if your setup records on motion: &lt;code&gt;cameraDelay&lt;/code&gt;, "Predefined duration after detection when further activity is ignored. Expressed in seconds." During that window a lingering animal is one clip and a second animal arriving behind it may be no clip at all. If your setup records continuously, the field stays empty. If it records on motion, the delay is a setting worth finding and writing down, because it shapes every count that follows.&lt;/p&gt;

&lt;p&gt;Then there is &lt;code&gt;timestampIssues&lt;/code&gt;, a flag for deployments whose media timestamps are "known to have (unsolvable) issues (e.g. unknown timezone, am/pm switch)". The standard keeps a place for a clock it cannot repair rather than dropping the data or pretending the clock was fine. That is a good habit on its own: if you are not sure the phone's clock was right, say so next to the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gaps belong in the structure, not in a note
&lt;/h2&gt;

&lt;p&gt;The deployments table has a start and an end, and I read the full field list for anything describing an interruption inside a deployment. There is a free-text &lt;code&gt;deploymentComments&lt;/code&gt; field and nothing structured for downtime. So under this layout, a camera that stopped for a day and a half reads most cleanly as two deployments, not one deployment with a caveat. That is my reading of the schema rather than a rule the spec states, and it is the habit worth borrowing: when the phone was unplugged, the battery ran flat, or someone lifted it down to look at it, close the row, and open a new one when it is running again.&lt;/p&gt;

&lt;p&gt;This matters because a gap is where false nulls live. A night with no clips is evidence that nothing came only if the camera was running that night. Count empty nights against a calendar and every night the camera was dark gets counted as a night nothing visited.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blanks are observations too
&lt;/h2&gt;

&lt;p&gt;The observations table has a required type with six allowed values: "animal, human, vehicle, blank, unknown, unclassified".&lt;/p&gt;

&lt;p&gt;Blank is a category of its own. A clip set off by wind, a headlight sweep or a moth can be recorded as blank rather than deleted. Keeping blanks earns its space twice. They show the camera was alive at that hour, and their share tells you whether a placement is mostly wind and headlights before you spend evenings reviewing it. The standard also has a &lt;code&gt;cameraSetupType&lt;/code&gt; field whose two values are setup and calibration, so the clips of you adjusting the mount are labelled as that instead of being counted as a visitor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Count events, not files
&lt;/h2&gt;

&lt;p&gt;The subtlest definition in the spec is &lt;code&gt;observationLevel&lt;/code&gt;. Observations at the media level are tied to a single file and are "especially useful for machine learning and don't need to be mutually exclusive (e.g. multiple classifications are allowed)". Observations at the event level cover a group of files and "should be mutually exclusive, so that their &lt;code&gt;count&lt;/code&gt; can be summed."&lt;/p&gt;

&lt;p&gt;The practical version: a raccoon that ambles through over several minutes may land in more than one file, especially if a recorder splits long recordings into segments. Tally sightings per file and that single visit is counted as many times as there are files. Group the files into one event first, then count. The spec defines an event as a collection of media files and, in the fields I read, sets no time rule for how to group them, so pick a rule, write it down, and keep it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A rate needs a denominator
&lt;/h2&gt;

&lt;p&gt;Here is the whole idea in a small script. Two files, shaped like the standard's tables with only the columns needed. The first is the deployment log, kept by hand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deploymentID,deploymentStart,deploymentEnd,cameraHeight,cameraTilt,cameraHeading,detectionDistance,timestampIssues,deploymentComments
yard-01,2026-10-01T18:00:00-04:00,2026-10-04T07:30:00-04:00,0.5,0,200,6.5,false,phone in fence-post box
yard-02,2026-10-05T19:15:00-04:00,2026-10-09T07:00:00-04:00,0.5,0,200,6.5,false,restarted after charger unplugged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second holds event-level observations. Notice that &lt;code&gt;o6&lt;/code&gt; sits in the day and a half between the two deployments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;observationID,deploymentID,eventStart,eventEnd,observationLevel,observationType,scientificName,count
o1,yard-01,2026-10-01T18:02:10-04:00,2026-10-01T18:02:40-04:00,event,human,,1
o2,yard-01,2026-10-02T02:14:00-04:00,2026-10-02T02:15:30-04:00,event,animal,Procyon lotor,2
o3,yard-01,2026-10-03T23:40:00-04:00,2026-10-03T23:41:00-04:00,event,blank,,
o4,yard-02,2026-10-06T01:05:00-04:00,2026-10-06T01:06:00-04:00,event,animal,Procyon lotor,1
o5,yard-02,2026-10-07T21:30:00-04:00,2026-10-07T21:31:00-04:00,event,animal,Vulpes vulpes,1
o6,yard-02,2026-10-04T23:00:00-04:00,2026-10-04T23:01:00-04:00,event,animal,Procyon lotor,1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script divides animal events by the hours the log says the camera was out, and refuses to quietly count anything that falls outside a logged window. Timestamps without an offset are rejected outright:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromisoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Z&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;+00:00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tzinfo&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;no UTC offset: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;

&lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deployments.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deploymentStart&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deploymentEnd&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deploymentID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deploymentID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;effort: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; camera-days over &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; deployments&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outside&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;observations.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;observationLevel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;event&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;observationType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;animal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deploymentID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;eventStart&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;outside&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;observationID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;scientificName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;most_common&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; events, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; per 100 camera-days&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;outside&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;outside their deployment window:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outside&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run with Python 3.10, it prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;effort: 6.05 camera-days over 2 deployments
Procyon lotor: 2 events, 33.0 per 100 camera-days
Vulpes vulpes: 1 events, 16.5 per 100 camera-days
outside their deployment window: o6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things in that output are worth more than the rates themselves.&lt;/p&gt;

&lt;p&gt;First, the rate uses 6.05 camera-days, not the calendar span. The same records counted from the first start to the last end cover 7.54 days, and dividing the two raccoon events by that gives 26.5 per 100 instead of 33.0, because 1.49 of those days had no camera watching. The calendar version is wrong in the comfortable direction: it makes a place look quieter than it is.&lt;/p&gt;

&lt;p&gt;Second, &lt;code&gt;o6&lt;/code&gt; is reported, not counted. The log says the camera was off, and a record says it was on. One of the two is wrong: either the restart went unlogged, or the clip carries a bad timestamp, which is exactly what &lt;code&gt;timestampIssues&lt;/code&gt; exists to flag. The script cannot tell which, and it should not guess. Counting it would lift the raccoon rate to 39.8 per 100 calendar days, with nothing in the output to show where the extra visit came from.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;count&lt;/code&gt; column holds individuals per event, and the script ignores it on purpose. Two raccoons in one clip is one visit; summing individuals answers a different question, and mixing the two inside one number is how a tally inflates.&lt;/p&gt;

&lt;p&gt;Small numbers deserve a plain warning. Three events over six days is an anecdote with a unit attached. The unit is still the point: it is what lets you compare this month with next month, or the fence post with the shed, as long as both denominators are written down. Move the phone, change its height or heading, and that is a new deployment, since a rate from one setup says little about another.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did not establish
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Whether rates from a phone camera can be compared with rates from a dedicated trail camera. Lens, trigger and night illumination all differ, and I have no data on how much that moves a count.&lt;/li&gt;
&lt;li&gt;How researchers in a given study define an independent event. The standard leaves room for the rule; it does not supply one in the fields I read.&lt;/li&gt;
&lt;li&gt;How any particular app names, splits or timestamps its files. I am describing a published data standard and a short script, not the internals of my own product or anyone else's.&lt;/li&gt;
&lt;li&gt;Which version of the specification a future reader will see. I read the data page and FAQ as fetched for this piece, and both can change.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;referrer=utm_source%3Ddevto%26utm_medium%3Darticle%26utm_campaign%3D2026w41" rel="noopener noreferrer"&gt;Background Camera RemoteStream on Google Play&lt;/a&gt; -- record with the screen off and keep the footage on the phone. Setup notes and other write-ups are at &lt;a href="https://superfunicular.com" rel="noopener noreferrer"&gt;superfunicular.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources.&lt;/strong&gt; &lt;a href="https://camtrap-dp.tdwg.org/data/" rel="noopener noreferrer"&gt;Camtrap DP data specification&lt;/a&gt; and &lt;a href="https://camtrap-dp.tdwg.org/faq/" rel="noopener noreferrer"&gt;Camtrap DP frequently asked questions&lt;/a&gt;, both maintained by the Camtrap DP Development Team under TDWG. Quotations are verbatim from the data page as fetched. A count tells you what came; the deployment log tells you whether anyone was watching, and only the two together say how often.&lt;/p&gt;

</description>
      <category>android</category>
      <category>python</category>
      <category>opendata</category>
      <category>wildlife</category>
    </item>
    <item>
      <title>Re-Muxing a Phone Video With ffmpeg Kept Where It Was Shot and Dropped When</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Mon, 12 Oct 2026 01:07:07 +0000</pubDate>
      <link>https://dev.to/superfunicular/re-muxing-a-phone-video-with-ffmpeg-kept-where-it-was-shot-and-dropped-when-1jdp</link>
      <guid>https://dev.to/superfunicular/re-muxing-a-phone-video-with-ffmpeg-kept-where-it-was-shot-and-dropped-when-1jdp</guid>
      <description>&lt;p&gt;I copied a test clip with ffmpeg, changing nothing but the container, and the copy came out still saying where the clip was recorded while no longer saying when. That is the opposite of what most people want from a quick clean-up before sending a video to someone, and it is easy to miss, because the picture is identical and nothing on screen tells you the file's metadata moved.&lt;/p&gt;

&lt;p&gt;This piece is about location data inside phone video files: where Android's recording API puts it, how to read it with &lt;code&gt;ffprobe&lt;/code&gt;, and which &lt;code&gt;ffmpeg&lt;/code&gt; commands remove it while keeping the recording time. I build a camera app for old Android phones. I am not describing how my app or any other app writes files; every result below comes from a clip I generated and tagged myself, with the commands shown so you can run them on your own footage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the coordinates go
&lt;/h2&gt;

&lt;p&gt;Android's &lt;code&gt;MediaRecorder&lt;/code&gt; class documents a method for exactly this. Its reference page says &lt;code&gt;setLocation&lt;/code&gt; will "Set and store the geodata (latitude and longitude) in the output file." It then says where and in what form: "The geodata is stored in udta box if the output format is OutputFormat.THREE_GPP or OutputFormat.MPEG_4, and is ignored for other output formats." And: "The geodata is stored according to ISO-6709 standard."&lt;/p&gt;

&lt;p&gt;Three things follow from those sentences.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The location lives in the container, in a user-data box, separate from the video frames. You cannot see it by watching the clip, and you cannot remove it by cropping or trimming the picture.&lt;/li&gt;
&lt;li&gt;It is written as text in a standard coordinate notation, a signed latitude followed by a signed longitude. Anything that can read container tags can print it.&lt;/li&gt;
&lt;li&gt;Whether a particular recording carries it depends on the app that made it and on that app's settings. The API makes it possible; it does not make it automatic. The file itself is the reliable witness to what it contains.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A test clip with a known location
&lt;/h2&gt;

&lt;p&gt;To have something to measure, I made two short clips, one MP4 and one MOV, both tagged with a recording time and with coordinates a short walk from the Royal Observatory in Greenwich. Using a public landmark keeps my own location out of the example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;ext &lt;span class="k"&gt;in &lt;/span&gt;mp4 mov&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;ffmpeg &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-f&lt;/span&gt; lavfi &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nv"&gt;testsrc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;320x240:rate&lt;span class="o"&gt;=&lt;/span&gt;15 &lt;span class="nt"&gt;-t&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-c&lt;/span&gt;:v libx264 &lt;span class="nt"&gt;-pix_fmt&lt;/span&gt; yuv420p &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-metadata&lt;/span&gt; &lt;span class="nv"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"+51.4779-000.0015/"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-metadata&lt;/span&gt; &lt;span class="nv"&gt;creation_time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2026-10-11T12:00:00Z"&lt;/span&gt; &lt;span class="s2"&gt;"clip.&lt;/span&gt;&lt;span class="nv"&gt;$ext&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;testsrc&lt;/code&gt; input is a synthetic colour-bar pattern, so the clips are tiny and contain nothing private. Everything below was run with ffmpeg 4.4.2 and Python 3.10.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading what a file says about itself
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ffprobe&lt;/code&gt; prints container tags. Asking for just the two tags this piece is about keeps the output short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffprobe &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-show_entries&lt;/span&gt; &lt;span class="nv"&gt;format_tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;location,creation_time &lt;span class="nt"&gt;-of&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;nw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 clip.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TAG:creation_time=2026-10-11T12:00:00.000000Z
TAG:location=+51.4779-000.0015/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the whole story of the clip in two lines: when it was recorded and where. Point the same command at a real phone recording before you share it. If the &lt;code&gt;location&lt;/code&gt; line is there, the coordinates of wherever the phone was standing travel with the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The quick copy that keeps the wrong half
&lt;/h2&gt;

&lt;p&gt;The most common thing people do to a video with &lt;code&gt;ffmpeg&lt;/code&gt; without re-encoding it is a stream copy into a new file, for example to rename the container or to trim it. Here is the plainest version, followed by the same tag check on the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-i&lt;/span&gt; clip.mp4 &lt;span class="nt"&gt;-c&lt;/span&gt; copy remux.mp4
ffprobe &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-show_entries&lt;/span&gt; &lt;span class="nv"&gt;format_tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;location,creation_time &lt;span class="nt"&gt;-of&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;nw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 remux.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TAG:location=+51.4779-000.0015/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The location came through. The recording time did not.&lt;/p&gt;

&lt;p&gt;The first half is documented. The &lt;code&gt;-map_metadata&lt;/code&gt; section of the ffmpeg manual says: "By default, global metadata is copied from the first input file, per-stream and per-chapter metadata is copied along with streams/chapters." Location is global metadata, so a plain copy carries it forward.&lt;/p&gt;

&lt;p&gt;The second half I can only report, not explain from the text I quoted. With ffmpeg 4.4.2 and no metadata options, &lt;code&gt;creation_time&lt;/code&gt; was absent from the output in my runs. I have not checked whether newer releases behave the same way, so treat this as a thing to test on your own build rather than a rule.&lt;/p&gt;

&lt;p&gt;For anyone keeping footage as a record, that combination matters. A copied clip that has lost its recording time but kept its coordinates is a worse record and a bigger privacy exposure at the same moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing everything
&lt;/h2&gt;

&lt;p&gt;The manual also describes the switch that turns automatic copying off: "A negative file index can be used to create a dummy mapping that just disables automatic copying." In practice that is &lt;code&gt;-map_metadata -1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-i&lt;/span&gt; clip.mp4 &lt;span class="nt"&gt;-c&lt;/span&gt; copy &lt;span class="nt"&gt;-map_metadata&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; stripped.mp4
ffprobe &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-show_entries&lt;/span&gt; &lt;span class="nv"&gt;format_tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;location,creation_time &lt;span class="nt"&gt;-of&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;nw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 stripped.mp4 | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second command counts the tag lines &lt;code&gt;ffprobe&lt;/code&gt; prints for the two keys, and the count is zero. Both the location and the recording time are gone.&lt;/p&gt;

&lt;p&gt;That is the right call for a clip headed somewhere public, where the time is as personal as the place. It is the wrong call for a clip you might need to rely on later, such as a recording of damage, a delivery or a dispute, where the time is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the time, dropping the place
&lt;/h2&gt;

&lt;p&gt;The version I would actually use asks for metadata to be copied, then overrides the one key that should not travel by setting it to an empty value. The MP4 file also had a language-suffixed copy of the same tag, so both names are cleared:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;f &lt;span class="k"&gt;in &lt;/span&gt;clip.mp4 clip.mov&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"nolocation.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;##*.&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  ffmpeg &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; copy &lt;span class="nt"&gt;-map_metadata&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-metadata&lt;/span&gt; &lt;span class="nv"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-metadata&lt;/span&gt; location-eng&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"== &lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  ffprobe &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-show_entries&lt;/span&gt; &lt;span class="nv"&gt;format_tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;location,creation_time &lt;span class="nt"&gt;-of&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;nw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;== nolocation.mp4
TAG:creation_time=2026-10-11T12:00:00.000000Z
== nolocation.mov
TAG:creation_time=2026-10-11T12:00:00.000000Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both containers keep their recording time and lose their coordinates. The explicit &lt;code&gt;-map_metadata 0&lt;/code&gt; matters here: it is what brings &lt;code&gt;creation_time&lt;/code&gt; back in my runs, in contrast to the bare copy above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking the bytes, not just the tags
&lt;/h2&gt;

&lt;p&gt;A tag reader shows you what it knows how to parse. To be sure the coordinates were removed from the file and not just hidden from one tool, I searched the raw bytes for the two location boxes that turned up in these clips and for the latitude written as text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="c1"&gt;# Byte-level check: does a location box or an ISO 6709 string survive?
&lt;/span&gt;&lt;span class="n"&gt;MARKERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;loci box&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;loci&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;©xyz box&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\xa9&lt;/span&gt;&lt;span class="s"&gt;xyz&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latitude text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+51.4779&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;MARKERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;none of the markers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 boxes.py clip.mp4 clip.mov remux.mp4 stripped.mp4 nolocation.mp4 nolocation.mov
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clip.mp4: loci box
clip.mov: ©xyz box, latitude text
remux.mp4: loci box
stripped.mp4: none of the markers
nolocation.mp4: none of the markers
nolocation.mov: none of the markers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details from that output are worth keeping in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The two containers stored the same coordinates differently. The MP4 that ffmpeg wrote used a &lt;code&gt;loci&lt;/code&gt; box, and a text search for the latitude finds nothing in it even though the location is present, so the box evidently does not store the coordinates as readable text. The MOV used a &lt;code&gt;©xyz&lt;/code&gt; box with the coordinate string in plain text. A search for the digits alone would have reported the MP4 as clean when it was not.&lt;/li&gt;
&lt;li&gt;The plain copy, &lt;code&gt;remux.mp4&lt;/code&gt;, still holds its &lt;code&gt;loci&lt;/code&gt; box, which agrees with the tag check above. The stripped and cleaned files hold none of the three markers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, I confirmed that none of this touched the picture. Extracting the video stream from three of the files and hashing it gives the same value each time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;f &lt;span class="k"&gt;in &lt;/span&gt;clip.mp4 stripped.mp4 nolocation.mp4&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;ffmpeg &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-map&lt;/span&gt; 0:v &lt;span class="nt"&gt;-c&lt;/span&gt; copy &lt;span class="nt"&gt;-f&lt;/span&gt; h264 - | &lt;span class="nb"&gt;md5sum&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-c1-12&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c1d2fe78b45f
c1d2fe78b45f
c1d2fe78b45f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same frames, different envelope.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short routine for clips you share
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run the &lt;code&gt;ffprobe&lt;/code&gt; tag check on the file you are about to send.&lt;/li&gt;
&lt;li&gt;If a &lt;code&gt;location&lt;/code&gt; tag is present and the clip is going anywhere public, use the keep-the-time command above, or &lt;code&gt;-map_metadata -1&lt;/code&gt; if the time should go as well.&lt;/li&gt;
&lt;li&gt;Re-run the tag check on the output, and for anything sensitive, the byte check too.&lt;/li&gt;
&lt;li&gt;Keep the original, untouched, somewhere only you control. The cleaned copy is for sharing; the original is the record.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I did not establish
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What any particular camera app writes. The Android reference describes what the API can do. Some apps expose a setting for location tags and some do not; the file is the thing to check.&lt;/li&gt;
&lt;li&gt;What happens on upload. I did not test whether any video site, messaging app or phone share sheet removes location from a video file, and I would not assume it does.&lt;/li&gt;
&lt;li&gt;Per-stream tags and other metadata formats. I checked file-level tags and three byte markers. Some phones and editors write additional metadata blocks, and a thorough audit would look for those too.&lt;/li&gt;
&lt;li&gt;Why the plain copy dropped &lt;code&gt;creation_time&lt;/code&gt;. I observed it on one ffmpeg build and did not trace the cause.&lt;/li&gt;
&lt;li&gt;How accurate the stored coordinates are on a real recording. A tag can only be as good as the position fix the phone had when it was written.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;referrer=utm_source%3Ddevto%26utm_medium%3Darticle%26utm_campaign%3D2026w42" rel="noopener noreferrer"&gt;Background Camera RemoteStream on Google Play&lt;/a&gt; -- record with the screen off and keep the footage on the phone. Setup notes and other write-ups are at &lt;a href="https://superfunicular.com" rel="noopener noreferrer"&gt;superfunicular.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources.&lt;/strong&gt; The &lt;a href="https://developer.android.com/reference/android/media/MediaRecorder" rel="noopener noreferrer"&gt;Android MediaRecorder API reference&lt;/a&gt;, &lt;code&gt;setLocation&lt;/code&gt; section, and the &lt;a href="https://ffmpeg.org/ffmpeg.html" rel="noopener noreferrer"&gt;ffmpeg command-line documentation&lt;/a&gt;, &lt;code&gt;-map_metadata&lt;/code&gt; section. Quotations are verbatim from both pages as fetched. Test results come from the scripts above, run as shown.&lt;/p&gt;

</description>
      <category>ffmpeg</category>
      <category>privacy</category>
      <category>android</category>
      <category>video</category>
    </item>
    <item>
      <title>The National Archives Will Take Phone Video as a Permanent Record. Its List Names the Codec, Not the File Extension</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Sun, 11 Oct 2026 16:54:41 +0000</pubDate>
      <link>https://dev.to/superfunicular/the-national-archives-will-take-phone-video-as-a-permanent-record-its-list-names-the-codec-not-3dl0</link>
      <guid>https://dev.to/superfunicular/the-national-archives-will-take-phone-video-as-a-permanent-record-its-list-names-the-codec-not-3dl0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; The U.S. National Archives publishes the file formats it accepts when a federal agency hands over records meant to be kept permanently. For digital video, the acceptable list includes the MPEG-4 wrapper with H.264 inside it, a combination many phone cameras can record. The list is written as wrapper plus codec, though, so a file ending in .mp4 is half an answer. HEVC, which many phones offer as a space-saving setting, does not appear in the digital video table at all. Beyond format, the same bulletin requires files that are valid against their specifications, no encryption standing between the archive and the content, and a retained copy until custody is confirmed. All three translate into checks anyone can run on a folder of recordings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nobody is going to accession your driveway footage. Still, the people whose job is keeping video readable for decades have written down, in plain tables, what they will take, and it is more specific than most advice about saving recordings. I read NARA Bulletin 2014-04, the appendix of tables it points to, and the Records Express post that announced the most recent change to the video rows. What follows is a close reading by someone who builds a camera app, aimed at developers and anyone else holding a large pile of phone video. I am not an archivist, and this is federal agency guidance, which governs agencies and nobody else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the bulletin is for
&lt;/h2&gt;

&lt;p&gt;The bulletin defines the property it is screening for, and the definition is narrower than a general idea of a good format:&lt;/p&gt;

&lt;p&gt;"Sustainability, as it relates to electronic file formats, is the suitability of a format to preserve encoded information over time."&lt;/p&gt;

&lt;p&gt;Note what is absent. Picture quality, file size and popularity of a particular app are not in the sentence. The question is whether the bits can still be turned back into the picture by someone else, later, with software that exists then.&lt;/p&gt;

&lt;p&gt;The appendix splits moving images into two groups. Digital cinema covers digitized film. Digital video is described as "including both video digitized from analogue sources and born digital video", and born digital video is what a phone produces.&lt;/p&gt;

&lt;h2&gt;
  
  
  The video table, read as a developer would
&lt;/h2&gt;

&lt;p&gt;The bulletin explains why the table has more than one column, and this is the part I would put in front of anyone who has ever told someone to just save it as MP4:&lt;/p&gt;

&lt;p&gt;"Many file formats, especially those used with digital audio and video, are composed of multiple parts, including a wrapper, which is the file format, and an embedded encoding stream or codec."&lt;/p&gt;

&lt;p&gt;Then it attaches a requirement to both parts:&lt;/p&gt;

&lt;p&gt;"Agencies must submit electronic records in files that are valid both according to the wrapper and any specified codec standards."&lt;/p&gt;

&lt;p&gt;So the digital video table names a wrapper and a codec on each row. As fetched for this piece, its acceptable formats include uncompressed AVI and uncompressed QuickTime, Windows Media Video with VC-1, MPEG-2 video, MXF carrying losslessly compressed J2K, and the row that matters to phone owners: MPEG 4, with H.264 in the codec column.&lt;/p&gt;

&lt;p&gt;That row is the good news in this reading. H.264 inside an MPEG-4 file is a common output of phone cameras and of most video tools, and it sits on the acceptable list for records the federal government intends to keep permanently. A phone owner may already be holding files in a format the archive would take. The way to know is to check a file, which the commands further down do.&lt;/p&gt;

&lt;p&gt;What is not on the table is just as useful. I searched the fetched page for HEVC, H.265, VP9 and WebM and found none of them anywhere on the page. Many phones offer HEVC as a high-efficiency option, since it generally produces smaller files at similar quality. If that switch is on, the recordings are in a codec this table does not list.&lt;/p&gt;

&lt;p&gt;Here is the honest limit of that observation. The table does not give a reason for any individual absence. The bulletin does say what NARA weighs:&lt;/p&gt;

&lt;p&gt;"Criteria such as the availability of technical specifications and licensing restrictions will be used to determine whether a format is sustainable and appropriate for use with permanent electronic records."&lt;/p&gt;

&lt;p&gt;I can tell you HEVC is missing from the list. I cannot tell you, from these pages, whether that reflects a judgment against it or a review that has not happened. Anyone who claims to know which, citing only these documents, is guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The preferred row that looks like a typo
&lt;/h2&gt;

&lt;p&gt;The single preferred format in the digital video table is listed as AV1 Image File Format, AVIF, with AV1 as the codec. AVIF is better known as a still image format, so the entry is worth a second look. The Records Express post that announced it gives one reason:&lt;/p&gt;

&lt;p&gt;"To remain consistent with NARA's digitization and motion picture preservation labs, this update adds AVIF as a preferred format for Digital Video"&lt;/p&gt;

&lt;p&gt;That is the whole stated rationale. It ties the choice to what NARA's own labs produce, not to anything about consumer recording. For a phone owner the practical reading is modest: the preferred row describes how an archive lab digitizes, and the acceptable rows are where ordinary camera output lands.&lt;/p&gt;

&lt;p&gt;The tables also move. The bulletin says NARA "may add new formats as they are adopted for use with Federal records, or may remove those that become obsolete". A reading of this table is a reading of one date. The page I fetched says it was last reviewed in March.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three requirements that are about files, not formats
&lt;/h2&gt;

&lt;p&gt;Section eight of the bulletin lists steps agencies must take in all cases. Two of them apply cleanly to a home archive.&lt;/p&gt;

&lt;p&gt;The first concerns locks:&lt;/p&gt;

&lt;p&gt;"Deactivate passwords or other forms of file level encryption including digital rights management (DRM) technologies commonly used with audio, video, and some publications that impede access to record data"&lt;/p&gt;

&lt;p&gt;The archive's position is that a lock on the file is a dependency on whoever holds the key. For a household this is a question to ask of any camera system: when footage leaves the device, is it a plain file any player opens, or is it encrypted so that it opens only inside the vendor's viewer and account? The rule is written against the second kind.&lt;/p&gt;

&lt;p&gt;The second concerns copies:&lt;/p&gt;

&lt;p&gt;"Retain a copy of all permanent electronic records transferred to NARA until receiving official notification that NARA has accepted legal custody of the records."&lt;/p&gt;

&lt;p&gt;The rule has an end condition, and the end condition is confirmation from the receiving side, not completion on the sending side. Translated to a home setup: a recording copied to a laptop or a drive is not safe to delete from the phone because the copy finished. It is safe once the copy has been opened and played from where it landed.&lt;/p&gt;

&lt;p&gt;The third requirement is the validity rule already quoted, and it is the one with a practical trap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking a folder yourself
&lt;/h2&gt;

&lt;p&gt;Two commands from FFmpeg cover most of this. The first prints the codec of the video stream, which tells you which side of the HEVC line a file sits on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffprobe &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-select_streams&lt;/span&gt; v &lt;span class="nt"&gt;-show_entries&lt;/span&gt; &lt;span class="nv"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;codec_name &lt;span class="nt"&gt;-of&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;nw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1:nk&lt;span class="o"&gt;=&lt;/span&gt;1 clip.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a test clip encoded with x264 it prints &lt;code&gt;h264&lt;/code&gt;. On a test clip encoded with x265 it prints &lt;code&gt;hevc&lt;/code&gt;. To sweep a folder of files without spaces in their names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;f &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.mp4&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s '&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; ffprobe &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-select_streams&lt;/span&gt; v &lt;span class="nt"&gt;-show_entries&lt;/span&gt; &lt;span class="nv"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;codec_name &lt;span class="nt"&gt;-of&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;nw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1:nk&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second command decodes every frame and throws the output away, which is the closest thing a household has to a validity check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-i&lt;/span&gt; clip.mp4 &lt;span class="nt"&gt;-f&lt;/span&gt; null - 2&amp;gt; clip.decode.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the trap, found by testing rather than assumed. I made a short clip with its index at the front of the file, cut off the last quarter, and decoded it. FFmpeg printed errors about invalid NAL unit sizes and a partial file, and then exited with status zero. A script that only checks the exit code would have reported that broken file as fine. A clip with its index at the end, cut in half, failed differently: it refused to open and exited non-zero.&lt;/p&gt;

&lt;p&gt;So the check that matters is whether the log is empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; clip.decode.log &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'decode errors, read clip.decode.log'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two honest limits apply. A clean decode shows that this build of FFmpeg could read every frame, which is a necessary condition for validity and not a proof of it. NARA's bulletin does not name a validation tool, and I will not invent one for it. And the behaviour I describe is from the FFmpeg build in my test environment; other builds may report differently, which is exactly why the log, not the exit code, is the thing to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this reading does not cover
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Audio. The bulletin has a separate audio table, and a video file's audio track is held to it. I did not check what codec phone recordings use for sound.&lt;/li&gt;
&lt;li&gt;Metadata. NARA has a separate metadata bulletin. Timestamps and location data in a recording are outside this piece.&lt;/li&gt;
&lt;li&gt;Whether anything here binds a household. It does not. The value is that an institution with a long time horizon wrote its criteria down where anyone can read them.&lt;/li&gt;
&lt;li&gt;What any specific app writes. I am describing the published guidance and two FFmpeg commands, not the internals of my own product or anyone else's.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tables were read as fetched for this piece, the bulletin as revised in its current online form, and the Records Express post as originally published. All three can change, and the bulletin says plainly that the tables will.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;referrer=utm_source%3Ddevto%26utm_medium%3Darticle%26utm_campaign%3D2026w41" rel="noopener noreferrer"&gt;Background Camera RemoteStream on Google Play&lt;/a&gt; -- record with the screen off and keep the footage on the phone. Setup notes and other write-ups are at &lt;a href="https://superfunicular.com" rel="noopener noreferrer"&gt;superfunicular.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources.&lt;/strong&gt; &lt;a href="https://www.archives.gov/records-mgmt/bulletins/2014/2014-04.html" rel="noopener noreferrer"&gt;NARA Bulletin 2014-04, Format Guidance for the Transfer of Permanent Electronic Records&lt;/a&gt;, &lt;a href="https://www.archives.gov/records-mgmt/policy/transfer-guidance-tables.html" rel="noopener noreferrer"&gt;Appendix A tables of file formats&lt;/a&gt; and &lt;a href="https://records-express.blogs.archives.gov/2025/01/10/updated-transfer-guidance-tables/" rel="noopener noreferrer"&gt;the Records Express post on the updated transfer guidance tables&lt;/a&gt;. Quotations are verbatim from those pages as fetched. The archive asks for the same thing from every file it keeps: that a stranger with ordinary tools can open it later, and a folder of home video can be held to that standard without any agency involved.&lt;/p&gt;

</description>
      <category>android</category>
      <category>video</category>
      <category>ffmpeg</category>
      <category>archiving</category>
    </item>
    <item>
      <title>California Wrote a Windshield Exemption for Dashcams, and a Phone That Records the Whole Drive Does Not Fit Its Definition</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Sun, 11 Oct 2026 12:54:26 +0000</pubDate>
      <link>https://dev.to/superfunicular/california-wrote-a-windshield-exemption-for-dashcams-and-a-phone-that-records-the-whole-drive-does-p68</link>
      <guid>https://dev.to/superfunicular/california-wrote-a-windshield-exemption-for-dashcams-and-a-phone-that-records-the-whole-drive-does-p68</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; California bans almost anything stuck to a windshield, then lists exceptions. A phone used as a dashcam has to squeeze into one of two: the portable GPS exception, which covers navigation and nothing else, or the video event recorder exception, whose definition describes a device that loops and keeps only short clips around a jolt. A phone recording the whole trip to storage matches neither description. The mount that does not depend on matching a definition sits below the glass, on the dash or a vent, clear of your view.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I owe this piece to a correction. Our own &lt;a href="https://dev.to/superfunicular/best-android-dashcam-apps-that-wont-kill-your-battery-2026-25c0"&gt;roundup of Android dashcam apps&lt;/a&gt; talks about a sunlit windshield mount as if the windshield were simply where the phone goes, and an older list of ours suggests a vent or windshield mount in the same breath, as though the two were interchangeable. The heat advice in those pieces holds up. The placement advice skipped a question that the vehicle code answers before any battery or heat question gets a turn: is the thing allowed on the glass at all?&lt;/p&gt;

&lt;p&gt;I read three texts to find out: California's windshield section, Minnesota's, and the federal rule for commercial trucks. They disagree with one another in ways that are useful to see side by side. None of what follows is legal advice, and I am not a lawyer. It is a close reading of short statutes, aimed at people whose dashcam happens to be a retired phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  California starts from a flat ban
&lt;/h2&gt;

&lt;p&gt;The first sentence of &lt;a href="https://law.justia.com/codes/california/code-veh/division-12/chapter-4/section-26708/" rel="noopener noreferrer"&gt;California Vehicle Code section 26708&lt;/a&gt; is about as broad as a traffic rule gets: "A person shall not drive any motor vehicle with any object or material placed, displayed, installed, affixed, or applied upon the windshield or side or rear windows." A second sentence then reaches past the glass to anything in the cabin that "obstructs or reduces the driver's clear view through the windshield or side windows". So there are two separate questions for a phone on a mount. Is it on the glass? And wherever it is, does it cut into what the driver can see?&lt;/p&gt;

&lt;p&gt;Everything else in the section is a list of exceptions to the first sentence: mirrors, sun visors, a toll transponder in a small square at the top centre, certain stickers in the lower corners. Two of the exceptions are the ones a phone owner reaches for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The GPS exception.&lt;/strong&gt; A portable GPS may sit in a seven-inch square in the lower corner farthest from the driver, or a five-inch square in the lower corner nearest the driver and outside an airbag deployment zone, "if the system is used only for door-to-door navigation while the motor vehicle is being operated". That condition is the whole point. A phone mounted there and showing turn-by-turn directions is the case the paragraph was written for. A phone mounted there with the screen off, recording the road for the whole trip, is doing a different job, and the paragraph does not describe it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The video event recorder exception.&lt;/strong&gt; This is the paragraph people mean when they say California allows dashcams on the windshield, and it allows the same two lower-corner squares plus a five-inch square at the top centre. But it comes with its own definition. A video event recorder, for this section, is "a video recorder that continuously records in a digital loop, recording audio, video, and G-force levels, but saves video only when triggered by an unusual motion or crash or when operated by the driver to monitor driver performance". The same paragraph then caps what such a device may store at no more than thirty seconds either side of a triggering event, requires a notice posted where passengers can see it stating that "a passenger's conversation may be recorded", and adds: "The registered owner or lessee of the vehicle may disable the device."&lt;/p&gt;

&lt;p&gt;Read that definition against how a phone is typically set up for dashcam duty. Most people start a recording when they pull out and stop it when they park, and the file is the trip. The definition describes something else: a rolling buffer that is thrown away unless a jolt, a crash or the driver's own button tells it to keep a short clip. Whether a phone app that does loop and trigger, and caps what it keeps, could fit the paragraph is a question I could not settle. I found no California guidance that applies the definition to a phone app either way. What I can say from the text is that a phone recording continuously to storage is not what the definition describes, so leaning on this exception for it is a bet, not a reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  The phone law already names a better spot
&lt;/h2&gt;

&lt;p&gt;California has a second statute that matters here, because it is written about phones rather than cameras. &lt;a href="https://codes.findlaw.com/ca/vehicle-code/veh-sect-23123-5/" rel="noopener noreferrer"&gt;Section 23123.5&lt;/a&gt; is the hands-free rule. It lets a driver operate a phone by hand only if the phone is mounted on the windshield in the same manner as the portable GPS above, or is "mounted on or affixed to a vehicle's dashboard or center console in a manner that does not hinder the driver's view of the road", and only for a touch made "with the motion of a single swipe or tap of the driver's finger".&lt;/p&gt;

&lt;p&gt;That statute is about touching the phone, not about recording with it, so it does not settle the windshield question for a dashcam. What it does is name, in so many words, the place the legislature expects a phone to live in a car: on the dashboard or the centre console, out of the way of the road. A phone mounted there is off the glass, which takes the first sentence of section 26708 out of play, and leaves only the clear-view test, which any placement has to pass anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minnesota asks a different question
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.revisor.mn.gov/statutes/cite/169.71" rel="noopener noreferrer"&gt;Minnesota Statutes section 169.71&lt;/a&gt; is not built around things stuck to the glass. Its prohibition is on driving with "any objects suspended between the driver and the windshield", followed by a list of exceptions. Two of them look relevant. One covers "driver feedback and safety monitoring equipment when mounted immediately behind, slightly above, or slightly below the rearview mirror". Another covers "global positioning systems or navigation systems when mounted or located near the bottommost portion of the windshield".&lt;/p&gt;

&lt;p&gt;So the Minnesota map is close to the reverse of California's. California's camera exception offers the lower corners and the top centre; Minnesota's monitoring-equipment exception points at the mirror, and its navigation exception points at the bottom of the glass. A phone recording the road from behind the mirror might count as driver feedback and safety monitoring equipment. The statute does not define that phrase in the subdivision I read, and I found nothing that applies it to a phone, so this is an open question rather than a permission.&lt;/p&gt;

&lt;p&gt;The broader lesson is that a mount position that is fine in one state can sit outside the exception in the next. A suction cup moves easily. The statute it has to satisfy does not move with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trucks get the clearest rule, and it names cameras
&lt;/h2&gt;

&lt;p&gt;The federal rule for commercial motor vehicles, &lt;a href="https://www.ecfr.gov/current/title-49/subtitle-B/chapter-III/subchapter-B/part-393/subpart-D/section-393.60" rel="noopener noreferrer"&gt;49 CFR 393.60&lt;/a&gt;, is the most explicit of the three, and of the texts I read it alone names cameras in its definitions. Ordinary windshield devices on a truck have to sit high, outside the wiper sweep, and "outside the driver's sight lines to the road and highway signs and signals". Devices that qualify as vehicle safety technology get their own placement limits instead, measured from the wiper sweep: one reaching eight and a half inches down from its top edge, one reaching seven inches up from its bottom edge, and the same sight-line test on top.&lt;/p&gt;

&lt;p&gt;The definition of vehicle safety technology, in &lt;a href="https://www.law.cornell.edu/cfr/text/49/393.5" rel="noopener noreferrer"&gt;49 CFR 393.5&lt;/a&gt;, lists a "driver camera system" among its examples, and closes by saying it includes "systems and devices that contain cameras, lidar, radar, sensors, and/or video". California's own section borrows that federal definition for the commercial vehicles it lists elsewhere in its code. None of this governs a private car. It is worth reading anyway, because it shows what a regulator writes down when it sets out to permit windshield cameras deliberately: a band measured from the wipers, and a sight-line test that applies to every device regardless of what it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would check before the mount goes up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read your own state's windshield section.&lt;/strong&gt; Every state I looked at has one, and they are short. Search for your state's vehicle code together with the words windshield and obstruction, and read the list of exceptions in full rather than a summary of it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Work out which exception your setup would claim, if any.&lt;/strong&gt; If the answer is the GPS one, the phone has to be navigating. If it is a camera exception, compare the statute's definition with what your recording app is set to do, not with what the device is called on the box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer a dash or vent mount for recording.&lt;/strong&gt; Off the glass, low, and outside the arc of road you scan while driving. In California that position is named outright in the hands-free statute, and it avoids the definitional question entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat cabin audio as its own decision.&lt;/strong&gt; California puts a passenger notice on its camera exception for a reason. If you leave the microphone on, the people riding with you should know.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start and stop the recording before the car moves.&lt;/strong&gt; In California a touch while driving is limited to a single swipe or tap, and a phone mid-setup on a mount invites more than that.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I could not verify
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Whether California enforcement treats a phone running a loop-and-trigger app as a video event recorder. The definition is functional and says nothing about the hardware; I found no ruling or guidance either way.&lt;/li&gt;
&lt;li&gt;What Minnesota counts as driver feedback and safety monitoring equipment. The phrase appears in the exception without a definition in the subdivision I read.&lt;/li&gt;
&lt;li&gt;The other forty-eight states. I read two states and one federal rule. I would rather say that plainly than imply coverage I did not do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The texts quoted are the published versions I fetched: California's section 26708 as amended with effect from January 2026, its hands-free section as current at the start of this year, Minnesota's current statutes, and the federal regulation as shown on eCFR this month. Statutes change, and a mount usually outlives the version of the law that was in force when it went up.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;referrer=utm_source%3Ddevto%26utm_medium%3Darticle%26utm_campaign%3D2026w41" rel="noopener noreferrer"&gt;Background Camera RemoteStream on Google Play&lt;/a&gt; -- record with the screen off and keep the footage on the phone. Setup notes and other write-ups are at &lt;a href="https://superfunicular.com" rel="noopener noreferrer"&gt;superfunicular.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources.&lt;/strong&gt; &lt;a href="https://law.justia.com/codes/california/code-veh/division-12/chapter-4/section-26708/" rel="noopener noreferrer"&gt;California Vehicle Code section 26708 on Justia&lt;/a&gt;, &lt;a href="https://codes.findlaw.com/ca/vehicle-code/veh-sect-23123-5/" rel="noopener noreferrer"&gt;California Vehicle Code section 23123.5 on FindLaw&lt;/a&gt;, &lt;a href="https://www.revisor.mn.gov/statutes/cite/169.71" rel="noopener noreferrer"&gt;Minnesota Statutes section 169.71 from the Revisor of Statutes&lt;/a&gt;, &lt;a href="https://www.ecfr.gov/current/title-49/subtitle-B/chapter-III/subchapter-B/part-393/subpart-D/section-393.60" rel="noopener noreferrer"&gt;the federal glazing rule at eCFR&lt;/a&gt; and &lt;a href="https://www.law.cornell.edu/cfr/text/49/393.5" rel="noopener noreferrer"&gt;the federal definitions section at Cornell LII&lt;/a&gt;. Quotations are verbatim statutory and regulatory text as published. The glass in front of the driver belongs to the driver first, and the statutes read as if they were written by people who had sat behind a badly placed mount.&lt;/p&gt;

</description>
      <category>android</category>
      <category>dashcam</category>
      <category>privacy</category>
      <category>law</category>
    </item>
    <item>
      <title>Is My Phone Security Camera Exposed to the Internet on IPv6? A Local-Only, No-Cloud Check for Jio and Other IPv6 Networks</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Sun, 11 Oct 2026 07:17:51 +0000</pubDate>
      <link>https://dev.to/superfunicular/is-my-phone-security-camera-exposed-to-the-internet-on-ipv6-a-local-only-no-cloud-check-for-jio-3idk</link>
      <guid>https://dev.to/superfunicular/is-my-phone-security-camera-exposed-to-the-internet-on-ipv6-a-local-only-no-cloud-check-for-jio-3idk</guid>
      <description>&lt;p&gt;Yesterday we published a guide on &lt;a href="https://dev.to/superfunicular/should-you-leave-the-sim-card-in-an-old-phone-security-camera-a-dual-sim-guide-for-offline-wi-fi-587c"&gt;which SIM card to leave in an old phone security camera&lt;/a&gt;. One of its points was that on mobile data, people outside usually cannot connect in to the phone, because operators often share one IPv4 address between many customers.&lt;/p&gt;

&lt;p&gt;That is true for IPv4. It is not the whole story, and for a lot of readers it is not even the main story. On Reliance Jio, APNIC Labs measures about &lt;strong&gt;96% of users as IPv6-capable&lt;/strong&gt;. Across India as a whole, Google's own statistics show about &lt;strong&gt;68% of its users reaching Google over IPv6&lt;/strong&gt; (as of 9 October 2026). Many home broadband connections now hand out IPv6 too.&lt;/p&gt;

&lt;p&gt;IPv6 changes one assumption that most "local-only camera" advice quietly depends on. This piece explains which assumption, and gives you a two-phone test that answers the question for your own setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is my phone security camera exposed to the internet on IPv6?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Maybe, and you can check in a few minutes.&lt;/strong&gt; On IPv4 home Wi-Fi, the thing that usually keeps a phone's camera page off the internet is the router's address translation (NAT): the phone has a private address like &lt;code&gt;192.168.1.42&lt;/code&gt;, and nothing outside can start a connection to it unless you forward a port. On IPv6 there is normally no NAT. The phone gets an address that is valid on the whole internet. &lt;strong&gt;What keeps it private then is your router's IPv6 firewall, and that may or may not be switched on.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So the honest answer is not "yes" or "no". It is: &lt;strong&gt;find the phone's IPv6 address, then try to open the camera page on it from outside.&lt;/strong&gt; The steps are below.&lt;/p&gt;

&lt;p&gt;If you use &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w41" rel="noopener noreferrer"&gt;Background Camera RemoteStream&lt;/a&gt;: it records with the screen off to the phone's own storage and serves a live view from a small web server on the phone, for browsers on your own Wi-Fi. No account, no cloud, no subscription. The test below works the same for our app as for any other camera app with a built-in viewer. It gives you an answer about your network instead of a promise from a developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "local-only" used to work without anyone thinking about it
&lt;/h2&gt;

&lt;p&gt;Here is the IPv4 picture, the one most of us learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your router has &lt;strong&gt;one&lt;/strong&gt; public address.&lt;/li&gt;
&lt;li&gt;Every device inside gets a private address (&lt;code&gt;192.168.x.x&lt;/code&gt;, &lt;code&gt;10.x.x.x&lt;/code&gt;). These are not routable on the internet.&lt;/li&gt;
&lt;li&gt;When the phone opens a connection out, the router remembers it so the reply can find its way back.&lt;/li&gt;
&lt;li&gt;When someone outside tries to open a connection &lt;em&gt;in&lt;/em&gt;, the router has nothing to match it to, and drops it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last step is why a camera page "only works on my Wi-Fi" without you ever touching a firewall setting. We described it in more detail in &lt;a href="https://dev.to/superfunicular/how-to-watch-your-phones-camera-from-outside-your-home-network-without-port-forwarding-510p"&gt;how to watch your phone's camera from outside your home network without port forwarding&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;NAT was never designed as a security feature. It was designed to stretch a shortage of IPv4 addresses. The protection was a side effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  What IPv6 changes
&lt;/h2&gt;

&lt;p&gt;IPv6 was built so that address sharing would not be needed. RFC 4864, the IETF document about protecting home networks on IPv6, opens by saying so:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"IPv6 was designed with the intention of making NAT unnecessary, and this document shows how Local Network Protection (LNP) using IPv6 can provide the same or more benefits without the need for address translation."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Google's Android team said the same thing more plainly in 2025: &lt;em&gt;"When every device can get global IPv6 addresses, there is no need to use NAT for address sharing!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So on an IPv6 network, your camera phone typically has an address that is reachable, in principle, from anywhere. Whether a connection from outside actually arrives depends on one thing: &lt;strong&gt;does the router filter unsolicited incoming IPv6 traffic?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RFC 4864 says the router should:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"...provide a default configuration where incoming traffic is limited to return traffic resulting from outgoing packets"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the same "only replies come back in" behaviour you got from NAT, now done on purpose by a firewall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does my router block incoming IPv6 by default?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Often, but you cannot assume it.&lt;/strong&gt; The IETF's advice for home routers, RFC 6092, says a router should by default refuse unsolicited incoming connections. But RFC 6092 is an &lt;em&gt;informational&lt;/em&gt; document, not a rule. It also requires an easy "transparent mode" that lets everything in, and says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The transparent mode of operation MAY be the default configuration."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the main requirements document for home IPv6 routers, RFC 7084, &lt;em&gt;"takes no position on whether such functionality is enabled by default."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In plain English: many routers ship with the IPv6 firewall on. Some do not. Some ISPs ship a router with their own settings. Some routers have the IPv6 firewall as a separate switch from the IPv4 one, and people turn one off while fixing something else.&lt;/p&gt;

&lt;h2&gt;
  
  
  The phone has more than one IPv6 address
&lt;/h2&gt;

&lt;p&gt;Open your phone's IPv6 addresses and you will usually see several. On stock Android, tap your connected Wi-Fi network in Settings and look for a section called &lt;strong&gt;"IPv6 addresses"&lt;/strong&gt;. Menus differ between manufacturers, so on some phones you may need to look under "Advanced" or "Status".&lt;/p&gt;

&lt;p&gt;Here is how to read the list:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Starts with&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Reachable from the internet?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fe80:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Link-local. Only works on the same Wi-Fi.&lt;/td&gt;
&lt;td&gt;No. Routers must not forward it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;fd&lt;/code&gt; (or &lt;code&gt;fc&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Unique local. Like a private IPv4 address.&lt;/td&gt;
&lt;td&gt;Not expected to be routed on the internet.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;2&lt;/code&gt; or &lt;code&gt;3&lt;/code&gt; (for example &lt;code&gt;2405:&lt;/code&gt;, &lt;code&gt;2409:&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Global. Valid on the whole internet.&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes, unless something filters it.&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two more details matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Android uses temporary "privacy" addresses for outgoing connections.&lt;/strong&gt; In Android's own source code, IPv6 privacy addresses are switched on and preferred for connections the phone starts. RFC 8981 sets the default for these at one day of use and two days of life. They rotate. That protects you when browsing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A temporary address does not hide a server.&lt;/strong&gt; The phone also has a stable global address. A web server on the phone can be reached on that one. The rotating addresses are for leaving, not for being found.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a myth to drop: "IPv6 addresses are too long to guess, so nobody will find me." RFC 7707, the IETF's own study of how IPv6 networks get scanned, admits that brute-forcing a whole &lt;code&gt;/64&lt;/code&gt; network is infeasible, but warns that &lt;em&gt;"the search space for such attacks is typically much smaller than the one traditionally assumed."&lt;/em&gt; Addresses also leak through logs and apps. Don't rely on being hard to find.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two-phone test (about five minutes)
&lt;/h2&gt;

&lt;p&gt;You need the camera phone and one other phone that has mobile data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1. Note the camera page address.&lt;/strong&gt; Open your camera app's live view address as you normally do on your Wi-Fi (for example &lt;code&gt;http://192.168.1.42:8080&lt;/code&gt;). Write down the &lt;strong&gt;port number&lt;/strong&gt;, the part after the colon. Use whatever port your app shows you; &lt;code&gt;8080&lt;/code&gt; is only an example.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2. Note the camera phone's global IPv6 address.&lt;/strong&gt; In the Wi-Fi details, pick the address that starts with &lt;code&gt;2&lt;/code&gt; or &lt;code&gt;3&lt;/code&gt;. If there are several, try them one at a time. If there is no address starting with &lt;code&gt;2&lt;/code&gt; or &lt;code&gt;3&lt;/code&gt;, your Wi-Fi has no global IPv6 and this particular risk does not apply on Wi-Fi. Skip to the mobile data note below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3. Check the camera page on IPv6 at home first.&lt;/strong&gt; On a laptop or phone that is on the same Wi-Fi, type the address into the browser &lt;strong&gt;inside square brackets&lt;/strong&gt;, with the port after:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://[2405:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:8080/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The brackets are required. RFC 3986 says an IPv6 address in a URL is &lt;em&gt;"distinguished by enclosing the IP literal within square brackets."&lt;/em&gt; Without them the browser cannot tell where the address ends and the port begins.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the page &lt;strong&gt;loads&lt;/strong&gt; at home, the camera page answers on IPv6. Go to step 4.&lt;/li&gt;
&lt;li&gt;If it &lt;strong&gt;does not load&lt;/strong&gt; at home, the app's server is probably not reachable on that address. Step 4 will most likely also fail, but run it anyway for a clear answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 4. Make sure the second phone really has IPv6.&lt;/strong&gt; Turn Wi-Fi &lt;strong&gt;off&lt;/strong&gt; on the second phone, so it uses mobile data. Open &lt;code&gt;ipv6.google.com&lt;/code&gt;. That name only has an IPv6 address, so it only loads over IPv6.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it loads, the second phone can reach IPv6 sites. Continue.&lt;/li&gt;
&lt;li&gt;If it does not load, &lt;strong&gt;stop.&lt;/strong&gt; A failed test from this phone means nothing, because it could not have reached any IPv6 address. Try a phone on a different operator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This step matters. A test that cannot succeed cannot tell you that you are safe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5. Try the camera page from outside.&lt;/strong&gt; Still on mobile data, type the same bracketed address and port from step 3.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It loads:&lt;/strong&gt; your camera page is reachable from the internet. Fix this before you do anything else (see below).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It times out:&lt;/strong&gt; your router is dropping unsolicited IPv6 from outside, at least from this network. That is the result you want.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do it again after any router reset, firmware update, or change of ISP. Those are the moments when settings return to their defaults.&lt;/p&gt;

&lt;h2&gt;
  
  
  If the page loaded from outside
&lt;/h2&gt;

&lt;p&gt;Do these in order. Stop when the outside test times out.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Find the IPv6 firewall in your router.&lt;/strong&gt; In the router's admin page, look for words like "IPv6 firewall", "IPv6 filter", or "inbound filtering". Turn on the option that blocks incoming connections that were not requested. Then repeat step 5.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check for an IPv6 "pinhole" or exception.&lt;/strong&gt; Some routers let you open a specific device and port to the internet. If there is one for the camera phone, delete it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you cannot reach the router settings&lt;/strong&gt; (rented flat, shop, guesthouse, ISP-locked router), ask the person who controls it to switch IPv6 inbound filtering on. If that is not possible, consider turning IPv6 off for that Wi-Fi network on the router, if it allows it. Do not do this to a router you do not control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep a password on the camera page, and change any default.&lt;/strong&gt; This is true on IPv4 too. A password is the last line, not the first.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mobile data is a separate question
&lt;/h2&gt;

&lt;p&gt;Everything above is about your Wi-Fi router. If the camera phone itself is on &lt;strong&gt;mobile data&lt;/strong&gt;, the operator's network sits in front of it instead. Mobile networks can run their own IPv6 firewalls. We could not find a reliable public source showing which operators block incoming IPv6 to phones and which do not, so we will not guess. &lt;strong&gt;You cannot assume either way.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is one more reason for the advice in &lt;a href="https://dev.to/superfunicular/should-you-leave-the-sim-card-in-an-old-phone-security-camera-a-dual-sim-guide-for-offline-wi-fi-587c"&gt;the dual-SIM guide&lt;/a&gt;: if you only watch on your own Wi-Fi, the camera phone does not need mobile data at all. If you do run it on mobile data, the same test works. Get the phone's IPv6 address from its mobile network status, and try it from a second phone on another network.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the link-local address?
&lt;/h2&gt;

&lt;p&gt;You might think: "I'll just use the &lt;code&gt;fe80:&lt;/code&gt; address. It can't leave the Wi-Fi." That is true of the address. But two problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browsers will not open it. A link-local address needs a "zone" (which network card to use) written into the URL. The standard for that, RFC 6874, was withdrawn in 2025. The replacement, RFC 9844, says browser makers found it &lt;em&gt;"impracticable to support."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Using a local address yourself does not stop the server answering on the global one. The test above is the only thing that tells you that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For everyday viewing on your own Wi-Fi, the normal &lt;code&gt;192.168.x.x&lt;/code&gt; address your app shows is still the simplest choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more for "no cloud" setups
&lt;/h2&gt;

&lt;p&gt;A cloud camera sends its video out to a company's server, and you watch from there. Nothing needs to connect &lt;em&gt;in&lt;/em&gt; to the camera. That is part of what you are paying for.&lt;/p&gt;

&lt;p&gt;A local-only camera, like a phone with a built-in web viewer, does the opposite. Your browser connects straight to the phone. That is what keeps the video off other people's servers, and it is the whole point. But it also means the network around the phone has to do the job of keeping strangers out. On IPv4, NAT did that job by accident. On IPv6, a firewall does it on purpose, if it is on.&lt;/p&gt;

&lt;p&gt;We made a similar point in &lt;a href="https://dev.to/superfunicular/the-kimwolf-bust-just-outed-android-webcams-as-botnet-fodder-heres-the-question-every-57f0"&gt;the Kimwolf botnet piece&lt;/a&gt;: a camera should never need an open inbound port to be useful. IPv6 does not change that rule. It changes who is responsible for enforcing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;On IPv4,&lt;/strong&gt; NAT usually keeps a phone camera page private by accident.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On IPv6,&lt;/strong&gt; there is usually no NAT. Your router's IPv6 firewall does that job, and it is not guaranteed to be on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check, don't assume:&lt;/strong&gt; find the address starting with &lt;code&gt;2&lt;/code&gt; or &lt;code&gt;3&lt;/code&gt;, confirm the second phone loads &lt;code&gt;ipv6.google.com&lt;/code&gt;, then try &lt;code&gt;http://[address]:port/&lt;/code&gt; over mobile data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loads from outside?&lt;/strong&gt; Turn on the router's IPv6 inbound filter, delete any pinhole, and keep a password on the camera page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watching only at home?&lt;/strong&gt; The camera phone does not need mobile data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Background Camera RemoteStream turns an old Android phone into a camera that records with the screen off, keeps recordings on the phone, and shows a live view in any browser on your own Wi-Fi. It can also push to YouTube Live when you want to watch from outside. No account, no cloud storage, no subscription. It is free on &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w41" rel="noopener noreferrer"&gt;Google Play&lt;/a&gt;, and there is more at &lt;a href="https://superfunicular.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w41" rel="noopener noreferrer"&gt;superfunicular.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc4864" rel="noopener noreferrer"&gt;RFC 4864: Local Network Protection for IPv6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc6092" rel="noopener noreferrer"&gt;RFC 6092: Recommended Simple Security Capabilities in Customer Premises Equipment (CPE) for Providing Residential IPv6 Internet Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc7084" rel="noopener noreferrer"&gt;RFC 7084: Basic Requirements for IPv6 Customer Edge Routers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc4291" rel="noopener noreferrer"&gt;RFC 4291: IP Version 6 Addressing Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc4193" rel="noopener noreferrer"&gt;RFC 4193: Unique Local IPv6 Unicast Addresses&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc8981" rel="noopener noreferrer"&gt;RFC 8981: Temporary Address Extensions for Stateless Address Autoconfiguration in IPv6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc7707" rel="noopener noreferrer"&gt;RFC 7707: Network Reconnaissance in IPv6 Networks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc3986" rel="noopener noreferrer"&gt;RFC 3986: Uniform Resource Identifier (URI): Generic Syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9844" rel="noopener noreferrer"&gt;RFC 9844 (obsoletes RFC 6874)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://android-developers.googleblog.com/2025/09/simplifying-advanced-networking-with.html" rel="noopener noreferrer"&gt;Simplifying advanced networking with DHCP prefix delegation — Android Developers Blog, Sept 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://android.googlesource.com/platform/packages/modules/NetworkStack/+/refs/heads/main/src/android/net/ip/IpClient.java" rel="noopener noreferrer"&gt;Android NetworkStack IpClient source (IPv6 privacy extensions)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stats.labs.apnic.net/ipv6/IN" rel="noopener noreferrer"&gt;APNIC Labs IPv6 measurements, India&lt;/a&gt; (30-day average, read 11 October 2026)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.google.com/intl/en/ipv6/statistics.html" rel="noopener noreferrer"&gt;Google IPv6 statistics, per-country&lt;/a&gt; (India 68.27%, as of 9 October 2026)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>ipv6</category>
      <category>security</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Your Camera Phone Asks for Its Address Back Every Few Hours. Here Is the Conversation.</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Sat, 10 Oct 2026 04:28:58 +0000</pubDate>
      <link>https://dev.to/superfunicular/your-camera-phone-asks-for-its-address-back-every-few-hours-here-is-the-conversation-20g4</link>
      <guid>https://dev.to/superfunicular/your-camera-phone-asks-for-its-address-back-every-few-hours-here-is-the-conversation-20g4</guid>
      <description>&lt;p&gt;A few weeks ago I wrote a practical guide for people running an old Android phone as a camera on a router they cannot log into: &lt;a href="https://dev.to/superfunicular/every-guide-says-reserve-the-address-on-your-router-what-if-the-router-is-not-yours-1pe5"&gt;Every Guide Says "Reserve the Address on Your Router." What If the Router Is Not Yours?&lt;/a&gt;. Its advice boiled down to: read the address off the phone, keep the phone connected, and set a manual address only last.&lt;/p&gt;

&lt;p&gt;A reader replied that the static-IP step felt risky if you can't see the whole network, and that the lease-renewal part sounded solid. Both instincts are right, and the reason is in the protocol itself. This is the companion piece: the actual exchange between the phone and the router, read from RFC 2131, with a camera that never moves in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lease is a clock with three marks on it
&lt;/h2&gt;

&lt;p&gt;When the router lends your phone an address, it lends it for a fixed duration. The phone does not wait for that duration to run out. RFC 2131 gives the client two earlier deadlines:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"T1 is the time at which the client enters the RENEWING state and attempts to contact the server that originally issued the client's network address. T2 is the time at which the client enters the REBINDING state and attempts to contact any server."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And it gives defaults for both:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"T1 defaults to (0.5 * duration_of_lease). T2 defaults to (0.875 * duration_of_lease)."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are defaults. The router can send its own values, and the RFC also asks for some random "fuzz" around them so that every device on the network does not renew at the same moment. But the shape is fixed: halfway through, try the router that gave you the address; most of the way through, ask anyone; at the end, let go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Halfway: the quiet renewal
&lt;/h2&gt;

&lt;p&gt;At T1 the phone sends a single, ordinary request to the router it already knows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"At time T1 the client moves to RENEWING state and sends (via unicast) a DHCPREQUEST message to the server to extend its lease. The client sets the 'ciaddr' field in the DHCPREQUEST to its current network address."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note what this message is not. It is not "please give me an address." It is "I am already using this one; extend it." If the router answers, the clock starts again, and nothing about the phone's address changes.&lt;/p&gt;

&lt;p&gt;If the router does not answer, the phone does not panic. It waits "one-half of the remaining time until T2 (in RENEWING state) and one-half of the remaining lease time (in REBINDING state), down to a minimum of 60 seconds, before retransmitting." It keeps asking, politely, at shrinking intervals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is why "keep the phone on the network" works.&lt;/strong&gt; A device that stays connected starts asking to extend at the halfway mark. It has the entire second half of the lease to get a single yes. A camera that never leaves the room is about the best-behaved DHCP client there is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The end: when the address really is gone
&lt;/h2&gt;

&lt;p&gt;The failure case is stated just as plainly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If the lease expires before the client receives a DHCPACK, the client moves to INIT state, MUST immediately stop any other network processing and requests network initialization parameters as if the client were uninitialized."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From that point the phone is a stranger again. It starts the full request over, and nothing obliges the router to hand back the old address. This is the path that breaks your bookmark, and it needs the phone to have gone the whole second half of the lease without one successful renewal. On a phone that stays connected to a working router, that should not happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  The other path: rejoining after being away
&lt;/h2&gt;

&lt;p&gt;For a camera that stays put, the riskier moment is not the halfway renewal. It is the phone dropping off — Wi-Fi toggled, a power cut, the router restarting — and then coming back. Rejoining uses a shorter exchange the RFC calls INIT-REBOOT. In it, the "requested IP address" option is a &lt;strong&gt;MUST&lt;/strong&gt;: the phone names the address it had and asks to keep it.&lt;/p&gt;

&lt;p&gt;The router has three ways to respond:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Yes.&lt;/strong&gt; It sends an acknowledgement and the address is unchanged. This is the common case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No.&lt;/strong&gt; If the phone's idea of its address is wrong, "the server SHOULD send a DHCPNAK message to the client." The phone then has to start over and take whatever it is given.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing.&lt;/strong&gt; This is the interesting one. The RFC says: "If the DHCP server has no record of this client, then it MUST remain silent."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Think about what case 3 means for a router that lost its lease table when the power went out. The phone asks for its old address. The router has no record of the phone, so — by the specification — it says nothing at all.&lt;/p&gt;

&lt;p&gt;The phone retransmits; the RFC's example is "four times, for a total delay of 60 seconds." Then, if it still hears nothing, "the client MAY choose to use the previously allocated network address and configuration parameters for the remainder of the unexpired lease."&lt;/p&gt;

&lt;p&gt;So after a router reboot, the phone is allowed to keep its old address for a while without any router having agreed to it. Often that is harmless, and the address survives. What happens later depends on how that particular router handles the next request, and the RFC leaves room for different implementations there. This is exactly why the anchor article suggests reading the address again after the next real power cut: it is the one situation where your router's behaviour is not predictable from the specification alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the router knows it is the same phone
&lt;/h2&gt;

&lt;p&gt;All of this depends on the router recognising the phone. The RFC says the lease "is implicitly identified by the 'client identifier' or 'chaddr' and the network address." &lt;code&gt;chaddr&lt;/code&gt; is the client hardware address.&lt;/p&gt;

&lt;p&gt;Modern Android presents a randomized hardware address by default, which sounds as though it should break this. On a normal network it does not, because the default type is persistent per network. The anchor article quotes the Android Open Source Project documentation on that in detail, including the developer setting that changes it. The short version: unless that developer setting is switched on, the phone shows the router the same identity each time, and the requests above work as intended.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the manual address is the step to be careful with
&lt;/h2&gt;

&lt;p&gt;DHCP has a conflict check built in. After being given an address, the client "SHOULD perform a check on the suggested address to ensure that the address is not already in use," for example with an ARP request. If the address is taken, "the client MUST send a DHCPDECLINE message to the server," and the server must then "mark the network address as not available."&lt;/p&gt;

&lt;p&gt;That check, and the router's bookkeeping, belong to DHCP. When you type an address into the phone's Wi-Fi settings, you leave DHCP for that network. The router's pool does not know you have claimed that address, and DHCP's decline-and-mark step is not part of what happens. If you cannot see the router's pool, you are picking a number without any of the bookkeeping that normally keeps two devices off the same one. That is the reader's instinct, stated in protocol terms.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to take from it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A phone that stays connected renews its address from the halfway point of the lease, by unicast, to the same router. Continuous connection is the strongest tool you have that needs nothing from the router.&lt;/li&gt;
&lt;li&gt;The rejoin path is where the address is at risk, not the renewal path, and a router that forgot its table is required to stay silent.&lt;/li&gt;
&lt;li&gt;A manual address gives up DHCP's own conflict handling. Use it last, and only if your two readings show the address really moves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical steps, including the two-reading test, are in the original guide: &lt;a href="https://dev.to/superfunicular/every-guide-says-reserve-the-address-on-your-router-what-if-the-router-is-not-yours-1pe5"&gt;Every Guide Says "Reserve the Address on Your Router." What If the Router Is Not Yours?&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Background Camera RemoteStream&lt;/strong&gt; records with the screen off, keeps footage on the device rather than in anyone's cloud, and serves a live view from a built-in web server to any browser on your own network.&lt;/p&gt;

&lt;p&gt;Google Play: &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=com.superfunicular.digicam&lt;/a&gt;&lt;br&gt;
Site: &lt;a href="https://superfunicular.com" rel="noopener noreferrer"&gt;https://superfunicular.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rfc-editor.org/rfc/rfc2131.html" rel="noopener noreferrer"&gt;RFC 2131, Dynamic Host Configuration Protocol&lt;/a&gt; — R. Droms, March 1997. §4.4.5 (T1/T2, RENEWING, REBINDING, expiry, retransmission), §4.3.2 (INIT-REBOOT; silence when the server has no record), §3.2 (reusing a previous address; retransmission and continued use), §3.1 and §4.4.1 (address-in-use check and DHCPDECLINE), §4.3.3 (server marks a declined address not available).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://source.android.com/docs/core/connect/wifi-mac-randomization-behavior" rel="noopener noreferrer"&gt;MAC randomization behavior&lt;/a&gt; — Android Open Source Project, as quoted in the original guide.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>networking</category>
      <category>iot</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Should You Leave the SIM Card in an Old Phone Security Camera? A Dual-SIM Guide for Offline, Wi-Fi and Mobile Data Setups</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Sat, 10 Oct 2026 04:23:54 +0000</pubDate>
      <link>https://dev.to/superfunicular/should-you-leave-the-sim-card-in-an-old-phone-security-camera-a-dual-sim-guide-for-offline-wi-fi-587c</link>
      <guid>https://dev.to/superfunicular/should-you-leave-the-sim-card-in-an-old-phone-security-camera-a-dual-sim-guide-for-offline-wi-fi-587c</guid>
      <description>&lt;p&gt;Most old Android phones that become security cameras still have a SIM card inside. Often it is the old number from before the upgrade. Sometimes it is a cheap prepaid SIM that came with the phone. On a dual-SIM handset there may be two.&lt;/p&gt;

&lt;p&gt;Nobody decides to leave them there. They are just there. And those SIM slots change how the camera behaves: whether it spends money on data, whether it comes back after a power cut, and whether your bank's one-time passwords show up on a phone sitting on a shop shelf.&lt;/p&gt;

&lt;p&gt;This guide is for one question: &lt;strong&gt;which SIM, if any, should stay in the phone you use as a camera?&lt;/strong&gt; It is written for the common case: a budget or older Android phone, a home or small shop, data that is prepaid and not unlimited, and no wish to pay a monthly fee for a camera.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do I need a SIM card to use an old phone as a security camera?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; A phone with no SIM at all still joins Wi-Fi normally. If the camera app records to the phone's own storage and serves its live view on your local network, the SIM does nothing for either job.&lt;/p&gt;

&lt;p&gt;That is how &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w41" rel="noopener noreferrer"&gt;Background Camera RemoteStream&lt;/a&gt; works. It records with the screen off to the phone's storage. A small web server on the phone itself serves the live view to any browser on the same Wi-Fi. No account, no cloud, no subscription. You only need the internet, through Wi-Fi or a SIM, if you want to push a YouTube Live stream that can be watched from outside the building.&lt;/p&gt;

&lt;p&gt;So the real question is not "does the camera need a SIM?" It is "&lt;strong&gt;what does each SIM do while it sits in the camera phone?&lt;/strong&gt;"&lt;/p&gt;

&lt;h2&gt;
  
  
  What a SIM can do to a camera phone (that you did not ask for)
&lt;/h2&gt;

&lt;p&gt;Four things, in rough order of how often they cause trouble.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. It can spend mobile data.&lt;/strong&gt; If mobile data is switched on, Android can use it when the Wi-Fi is weak, has no internet, or is a shared network that needs a login. We explained why in &lt;a href="https://dev.to/superfunicular/why-your-phone-security-camera-uses-mobile-data-on-shared-wi-fi-captive-portals-explained-5ejn"&gt;why your phone security camera uses mobile data on shared Wi-Fi&lt;/a&gt;. With no SIM, or with mobile data off, that cannot happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. It can lock itself after a restart.&lt;/strong&gt; If the SIM has a SIM PIN turned on, Google's help page is direct: &lt;em&gt;"You'll be asked for your SIM PIN whenever you turn on your device."&lt;/em&gt; After a power cut drains the battery and the phone restarts, that SIM has no mobile network until someone types the PIN by hand. If your camera depends on that SIM for internet, it stays offline until you visit it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. It receives calls and messages.&lt;/strong&gt; A phone on a shelf still rings. It still lights up for SMS. And if the SIM is your main number, those messages include bank and app one-time passwords (OTPs), shown on a screen you are not holding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. It may be quietly deactivated.&lt;/strong&gt; Prepaid SIMs that are never used do not last forever. In India, TRAI's 2013 rule says a prepaid connection &lt;em&gt;"shall not be deactivated for any period of non-usage less than 90 days"&lt;/em&gt;. That is a minimum, not a promise of more. Rules differ in Bangladesh, Iraq, Algeria and elsewhere, so check with your operator. A data SIM you set up once and forgot can stop working months later.&lt;/p&gt;

&lt;p&gt;None of this is a fault in the camera app. It is the phone still being a phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which SIM should stay in the phone? Four common setups
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Setup 1: Home or shop with Wi-Fi, you watch on the same Wi-Fi
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Take the SIM out.&lt;/strong&gt; You lose nothing. Recording and the local live view both run without the internet. This is the true offline security camera: no SIM, no cloud, and nothing that can spend money.&lt;/p&gt;

&lt;p&gt;If you cannot remove it (a tight tray, a glued back), turn mobile data off for that SIM instead, and turn off any option that switches to mobile data when the Wi-Fi is poor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup 2: No router at all, using another phone's hotspot
&lt;/h3&gt;

&lt;p&gt;The camera phone still needs &lt;strong&gt;no SIM&lt;/strong&gt; for local viewing. Two phones on the same hotspot talk to each other directly; the live view is local traffic and does not need the internet, so mobile data can stay off. Either phone can make the hotspot. If the camera phone is the one making it and refuses to turn the hotspot on with no SIM inside (some phones behave this way), let the viewing phone make the hotspot instead and have the camera phone join it. The full setup, and what to check, is in &lt;a href="https://dev.to/superfunicular/how-to-use-an-old-phone-as-a-security-camera-without-a-wi-fi-router-the-hotspot-setup-nobody-1bd5"&gt;how to use an old phone as a security camera without a Wi-Fi router&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup 3: You want to watch from outside, over mobile data
&lt;/h3&gt;

&lt;p&gt;This is the one setup where a SIM in the camera phone earns its place. Keep &lt;strong&gt;one&lt;/strong&gt; data SIM and set it up on purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose it as the data SIM.&lt;/strong&gt; Google's Pixel help says: &lt;em&gt;"Only one SIM can be the default for data."&lt;/em&gt; On a Pixel the setting is under &lt;strong&gt;Settings &amp;gt; Network &amp;amp; internet &amp;gt; SIMs &amp;gt; Mobile data&lt;/strong&gt;. Samsung, Xiaomi, Realme and others put it in different menus. Look for "SIM manager", "Dual SIM" or "Mobile data SIM".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set a data limit.&lt;/strong&gt; On a Pixel it is under &lt;strong&gt;Settings &amp;gt; Network &amp;amp; internet &amp;gt; SIMs &amp;gt; Data warning &amp;amp; limit&lt;/strong&gt;. When the limit is reached, mobile data turns off and you get a notification. Google also warns that &lt;em&gt;"some carriers measure usage differently,"&lt;/em&gt; so set the limit below your real plan, not equal to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn the SIM PIN off on this SIM&lt;/strong&gt;, or accept that every restart needs a visit. A camera that cannot come back online by itself after a power cut is a camera you will find dead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is one more thing to know before you pay for data. &lt;strong&gt;On mobile data, people outside usually cannot connect in to the phone.&lt;/strong&gt; One reason is that an operator can put many customers behind one shared address, using its own network address translation. There is even an address range set aside for that kind of sharing (&lt;code&gt;100.64.0.0/10&lt;/code&gt;, in RFC 6598). Whether your operator does this, and how, is up to your operator. The same RFC notes that some applications &lt;em&gt;"cannot seed content due to the inability to open incoming ports"&lt;/em&gt;. So the local web viewer that works on your Wi-Fi does not normally become reachable from across town just because there is a SIM inside.&lt;/p&gt;

&lt;p&gt;What does work over mobile data is a connection the phone makes &lt;strong&gt;outward&lt;/strong&gt;, like pushing a YouTube Live stream. That is why Setup 3 usually means YouTube Live.&lt;/p&gt;

&lt;p&gt;And that uses real data. YouTube's own encoder guidance gives a &lt;strong&gt;minimum&lt;/strong&gt; and a &lt;strong&gt;recommended&lt;/strong&gt; bitrate for each quality. Converted to data per hour:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quality (H.264)&lt;/th&gt;
&lt;th&gt;YouTube minimum&lt;/th&gt;
&lt;th&gt;Data per hour at minimum&lt;/th&gt;
&lt;th&gt;YouTube recommended&lt;/th&gt;
&lt;th&gt;Data per hour at recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;480p, 30 fps&lt;/td&gt;
&lt;td&gt;0.4 Mbps&lt;/td&gt;
&lt;td&gt;about 180 MB&lt;/td&gt;
&lt;td&gt;4 Mbps&lt;/td&gt;
&lt;td&gt;about 1.8 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;720p, 30 fps&lt;/td&gt;
&lt;td&gt;3 Mbps&lt;/td&gt;
&lt;td&gt;about 1.35 GB&lt;/td&gt;
&lt;td&gt;8 Mbps&lt;/td&gt;
&lt;td&gt;about 3.6 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A 720p stream at YouTube's minimum, left on for a full day, is about 32 GB. On most prepaid plans that is not a 24/7 setup. Stream when you need it, at a low quality, and let the phone record locally the rest of the time. The figures above are calculated from YouTube's numbers. Your own phone's data usage screen is the real measure, and we wrote about &lt;a href="https://dev.to/superfunicular/what-happens-to-a-phone-security-camera-during-a-power-cut-or-an-internet-outage-they-are-not-the-40o5"&gt;measuring it yourself&lt;/a&gt; rather than trusting anyone's estimate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup 4: The SIM holds a number you still need for OTPs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Do not put it in the camera phone.&lt;/strong&gt; Move it to the phone you carry. A camera phone sits in one place, often where customers or visitors can reach it. If it is picked up, your OTPs go with it.&lt;/p&gt;

&lt;p&gt;If you truly have no choice, at least stop the lock screen from showing message text. On a Pixel: &lt;strong&gt;Settings &amp;gt; Notifications &amp;gt; Notifications on lock screen&lt;/strong&gt;, then turn off &lt;strong&gt;Show sensitive content&lt;/strong&gt;. Other brands have a similar "hide content" option under lock screen or notification settings. Also set the phone to silent, so it does not ring in an empty room at night.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dual-SIM phones: what to do with the second slot
&lt;/h2&gt;

&lt;p&gt;Many budget dual-SIM phones have two physical slots. The usual mistake is to fill both "because they are there". For a camera phone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Empty is best&lt;/strong&gt; unless you are using Setup 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One data SIM, chosen on purpose,&lt;/strong&gt; if you are streaming out. Leave the second slot empty so nothing else can receive calls, messages or data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never your main number,&lt;/strong&gt; for the reasons in Setup 4.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Newer phones add options such as using mobile data from both SIMs during calls, or switching data between SIMs automatically. These depend on your phone model and your operator. On a camera phone, turn off anything that lets data move to a SIM you did not choose.&lt;/p&gt;

&lt;h2&gt;
  
  
  A five-minute check after you set it up
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Restart the phone on purpose.&lt;/strong&gt; Does it come back to the network without you typing anything? If a SIM PIN prompt appears, you have found your power-cut problem today instead of later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unlock it once and open the camera app.&lt;/strong&gt; If you use a screen lock, Android does not run most apps after a restart until the phone is unlocked once. Its developer documentation says: &lt;em&gt;"By default, apps don't run during Direct Boot mode."&lt;/em&gt; Plan to unlock the phone after any restart, and check that recording has started again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open the live view from another device on the same Wi-Fi.&lt;/strong&gt; That confirms the local path, which needs no SIM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check mobile data usage the next day.&lt;/strong&gt; If the camera phone has no SIM, it should show nothing. If it has a data SIM, compare the number with what you expected from the table above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send the camera phone's number a test SMS&lt;/strong&gt; (if it has a SIM) and look at the lock screen. If you can read the message without unlocking, so can anyone at the counter.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What the documentation does not tell you
&lt;/h2&gt;

&lt;p&gt;Google's help pages describe each of these settings on a Pixel. They do not describe the same menus on Samsung, Xiaomi, Realme, Tecno or Infinix phones, which are most of the phones in this situation, so we have not printed paths for those brands. We have also not tried to say how long any particular operator keeps an unused SIM active outside India. And whether data from both SIMs can switch automatically depends on the phone and the operator, not only on Android. Test on your own phone before you rely on it.&lt;/p&gt;

&lt;p&gt;If your stream drops but recording continues, that is a different problem with its own fixes, covered in &lt;a href="https://dev.to/superfunicular/live-view-stopped-recording-did-not-three-reasons-an-old-phone-security-camera-loses-its-stream-3i35"&gt;live view stopped, recording did not&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Watching on the same Wi-Fi? &lt;strong&gt;No SIM.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Using a hotspot? &lt;strong&gt;No SIM in the camera phone.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Streaming out over mobile data? &lt;strong&gt;One data SIM, no SIM PIN, a data limit below your plan.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Your main number? &lt;strong&gt;Never in the camera phone.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Background Camera RemoteStream records with the screen off to the phone's own storage, serves a live view from a web server running on the phone itself, and can push to YouTube Live when you want a stream that reaches outside the building. No account, no cloud storage, no subscription. It is free on &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w41" rel="noopener noreferrer"&gt;Google Play&lt;/a&gt;, and there is more at &lt;a href="https://superfunicular.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w41" rel="noopener noreferrer"&gt;superfunicular.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://support.google.com/pixelphone/answer/9449293" rel="noopener noreferrer"&gt;Use dual SIMs with your Pixel phone — Pixel Phone Help&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.google.com/pixelphone/answer/2819524" rel="noopener noreferrer"&gt;Manage how your Pixel uses data — Pixel Phone Help&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.google.com/pixelphone/answer/15146908" rel="noopener noreferrer"&gt;Set a SIM PIN — Pixel Phone Help&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.android.com/privacy-and-security/direct-boot" rel="noopener noreferrer"&gt;Support Direct Boot mode — Android Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc6598" rel="noopener noreferrer"&gt;RFC 6598: IANA-Reserved IPv4 Prefix for Shared Address Space&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.google.com/youtube/answer/2853702" rel="noopener noreferrer"&gt;Choose live encoder settings, bitrates, and resolutions — YouTube Help&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cms.trai.gov.in/sites/default/files/2024-11/Information%20Note%20to%20the%20Press.pdf" rel="noopener noreferrer"&gt;TRAI press note 12/2013 (prepaid deactivation)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>privacy</category>
      <category>security</category>
      <category>mobile</category>
    </item>
    <item>
      <title>This week on @Digital_Nomad_Media — 13 new clips (2026-W39)</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Sun, 27 Sep 2026 14:04:28 +0000</pubDate>
      <link>https://dev.to/superfunicular/this-week-on-digitalnomadmedia-13-new-clips-2026-w39-3hnp</link>
      <guid>https://dev.to/superfunicular/this-week-on-digitalnomadmedia-13-new-clips-2026-w39-3hnp</guid>
      <description>&lt;p&gt;Quick weekly digest from my YouTube channel — every clip below is fresh in the last 7 days.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=4eTkZpLm9EU" rel="noopener noreferrer"&gt;Oops&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=4eTkZpLm9EU" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4dsdoq6ohfu160sfit9g.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;62s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=SI6ug9AnIjw" rel="noopener noreferrer"&gt;No children taller than red line allowed! ✌️🤠&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=SI6ug9AnIjw" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fujyyzlxaunir5gssbui0.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;68s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=0OILTX6jQGE" rel="noopener noreferrer"&gt;Every Time I try to go fishing........&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=0OILTX6jQGE" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcbog83hggf6frwm7kjbh.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;70s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=TTBY7teAIJ8" rel="noopener noreferrer"&gt;Digi Snippets ✌️🤠&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=TTBY7teAIJ8" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mnemqb0iht710drjfzy.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;64s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=awpgySAgGpk" rel="noopener noreferrer"&gt;Aww it was just an ol'aligator ✌️🤠&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=awpgySAgGpk" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk6m1uq7dm2t6ng2bjwuc.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;63s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=fRnEPErtiVs" rel="noopener noreferrer"&gt;How de do dat? ✌️🤠&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=fRnEPErtiVs" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8spprte03bm8gzflxmai.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;67s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=of5ErfUNB_E" rel="noopener noreferrer"&gt;#DreamScreenAI&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=of5ErfUNB_E" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2yr167y6zxl1xj3fkmmu.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;64s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=1qbQPibkDQk" rel="noopener noreferrer"&gt;My new box truck!&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=1qbQPibkDQk" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd5oqtgzd6yfzovqxqict.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;67s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=uhKr7RxJoOo" rel="noopener noreferrer"&gt;They brought him a phone. He messed with it for an hour and then........🤣&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=uhKr7RxJoOo" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo0h6lrmmf9hgy2kg3riz.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;78s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=a5XMZbZqPIo" rel="noopener noreferrer"&gt;Plow a Trail&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=a5XMZbZqPIo" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flup0jatn87vix0cimm0p.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;69s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=m3uud4MHthA" rel="noopener noreferrer"&gt;How I saved a damsel in distress in Grand Rapids Part 3.5&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=m3uud4MHthA" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmpioqb34ejfcxob3snxm.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;62s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=U6Rc8yoOQXk" rel="noopener noreferrer"&gt;Fish Guarding their nests photography filmed underwater w/ my Insta360 Go 2 in Grand Rapids Michigan&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=U6Rc8yoOQXk" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1118riqji5d2gtowafg0.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;62s&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.youtube.com/watch?v=sNVJtGypbeU" rel="noopener noreferrer"&gt;Elite K9 River Patrol&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=sNVJtGypbeU" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpljqhrbbnxdhx26dy9rt.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;77s&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  I also built an app — DigiCam
&lt;/h2&gt;

&lt;p&gt;I also made DigiCam, listed as Background Camera RemoteStream on Google Play. It's the world's first screen-off YouTube live streaming app: stream live with the screen off for ~10× the battery life, plus background recording, remote web console control, file-based YouTube Live, and playlists. Privacy-first, all local storage. Free with ads or Pro for the full feature set:&lt;br&gt;
&lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=com.superfunicular.digicam&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Watch the full channel: &lt;a href="https://www.youtube.com/@Digital_Nomad_Media" rel="noopener noreferrer"&gt;@Digital_Nomad_Media&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tags: #SuperFunicular #DigiCam #DigiNomad #YouTubeShorts #ContentCreator #LadyThePitbull #travel #trixietheterrible #DreamScreenAI #travelshorts&lt;/p&gt;

</description>
      <category>diginomad</category>
      <category>youtube</category>
      <category>indiedev</category>
      <category>digicam</category>
    </item>
    <item>
      <title>Which Faults Actually Disqualify an Old Phone From Camera Duty? A Triage List, Including the One We Get Wrong</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Mon, 21 Sep 2026 12:56:09 +0000</pubDate>
      <link>https://dev.to/superfunicular/which-faults-actually-disqualify-an-old-phone-from-camera-duty-a-triage-list-including-the-one-we-40b1</link>
      <guid>https://dev.to/superfunicular/which-faults-actually-disqualify-an-old-phone-from-camera-duty-a-triage-list-including-the-one-we-40b1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; The fault that quietly ruins the picture is the one nobody inspects: a scratch or hairline crack on the small window over the rear lens. It is filed as cosmetic because a phone lives in a pocket, and it turns every bright object in the scene into a permanent smear of scattered light in the same place in every frame. The fault that actually retires phones is the front display, and that is the one this job cares least about — though not for the reason we used to give here: what a setup session needs is a live touch layer, not a readable screen, and &lt;a href="https://dev.to/superfunicular/your-phones-screen-is-cracked-and-the-camera-still-works-setting-up-an-old-phone-security-camera-gia"&gt;we corrected that ourselves&lt;/a&gt;. Below is a triage table for every common fault, a five-minute inspection you can do before committing a handset, and an honest note about the line we have been repeating that skips all of this. Apps like &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;referrer=utm_source%3Ddevto%26utm_medium%3Darticle%26utm_campaign%3D2026w39" rel="noopener noreferrer"&gt;Background Camera RemoteStream&lt;/a&gt; run with the display off, which is exactly why the front-glass question turns out to be the easy one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Almost every article about reusing an old handset as a camera says some version of "any old phone will do." Almost every article about buying one says "check for damage." Neither one tells you &lt;em&gt;which&lt;/em&gt; damage, and the two are not the same list. A fault that makes a phone useless in a pocket can be irrelevant on a bracket, and a fault that nobody would return a phone for can wreck a picture permanently.&lt;/p&gt;

&lt;p&gt;Here is the triage I would actually run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fault that ends a phone's life is the one this job does not use
&lt;/h2&gt;

&lt;p&gt;A phone gets retired for its display more than for anything else. It is the largest, most exposed, most expensive-to-repair part, and once it is unreadable the device is unusable as a phone. So the pile of candidate camera handsets is heavily weighted towards cracked fronts.&lt;/p&gt;

&lt;p&gt;For this job that is close to the best possible news. A camera setup runs with the display off — that is the entire premise of leaving a phone recording for weeks — so the condition of the front glass stops mattering the moment setup is finished. What you need is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enough of the touch layer alive to complete setup &lt;strong&gt;once&lt;/strong&gt; — which is the binding requirement, not legibility.&lt;/li&gt;
&lt;li&gt;Nothing loose enough to fall out of the frame or short something.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is it. Cracks, dead pixels, colour shifts, a dim backlight, burn-in from a previous life as a dashboard: none of them affect a single frame of recorded video, because none of them are in the optical path. The picture is made by a sensor behind a different piece of glass entirely.&lt;/p&gt;

&lt;p&gt;There is one distinction inside this that matters more than the crack itself: &lt;strong&gt;broken glass and a dead touch layer are different faults.&lt;/strong&gt; Spiderwebbed glass that still registers taps is fine. A panel that shows an image but ignores your finger, or a panel that is simply black, is a phone you cannot configure by hand — but it is not a dead end. A wired mouse through a USB-OTG adapter gives you a pointer: Android has supported USB host mode since 3.1, no drivers, and it works on a locked phone. We walked that through, case by case, in &lt;a href="https://dev.to/superfunicular/your-phones-screen-is-cracked-and-the-camera-still-works-setting-up-an-old-phone-security-camera-gia"&gt;a separate piece on setting up a handset you cannot touch&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The piece of glass nobody inspects
&lt;/h2&gt;

&lt;p&gt;Now the other side. There is a small protective window over the rear camera, and it takes exactly the same impacts as the rest of the device. When it chips, scratches or crazes, three things happen at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bright objects smear.&lt;/strong&gt; Any strong light source in the scene — a bulb, a bright doorway, headlights turning in — gets scattered by the damage instead of passing cleanly through. You get a haze, a streak or a starburst radiating from that light.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It happens in the same place every time.&lt;/strong&gt; Unlike a smudge you can wipe, the damage is fixed relative to the sensor, so the artefact lands on the same part of the frame in every single frame, all day, for as long as the setup runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contrast falls across the whole image.&lt;/strong&gt; Scattered light does not only make a streak; it lifts the dark parts of the picture towards grey, which is precisely where the detail you wanted was hiding.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this shows up in the way people usually check a phone. A quick snapshot in even indoor lighting can look completely normal. It shows up when there is a strong light in view, which describes most of the situations a camera is pointed at: a door onto daylight, a window, a driveway at dusk, a room with a lamp in the corner.&lt;/p&gt;

&lt;p&gt;And crucially, nobody who later looks at that footage says "the lens window is chipped." They say the camera is bad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Triage table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fault&lt;/th&gt;
&lt;th&gt;Verdict for camera duty&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cracked or shattered front glass, touch still works&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fine&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Display is dark the whole time. Needs to survive one setup session.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display black or touch layer dead&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Workable&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not in the optical path. Setup runs off a wired mouse on a USB-OTG adapter, which works even on a locked phone.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scratch, chip or crack on the rear camera window&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Usually disqualifying&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Permanent scattered light in a fixed place in every frame; kills contrast around any bright object.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Greasy or hazy rear window, no physical damage&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free to fix&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A wipe. Do this before judging any picture, including one you are using to judge a phone you are buying.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Known water exposure in its history&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Treat as unknown, not as a pass&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Corrosion is slow and cannot be inspected from outside. It may run for years. It is not a device to put somewhere that matters and forget.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Battery will not hold a charge&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Less decisive here than elsewhere&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The device lives on a cable for this job. There is a lot written about phone batteries already and I am not going to re-run it here.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing SIM tray, no service, carrier-locked&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Irrelevant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The network story for this setup is Wi-Fi. A handset with no service is still a computer with a camera in it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dead speaker or microphone&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Depends entirely on whether you want sound&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent video is a complete answer for many uses and useless for others. Decide before, not after.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dead power button&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Real nuisance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A device you cannot restart by hand is a device that needs a plan for the day it needs restarting.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The five-minute inspection
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Wipe the rear window with a soft cloth. Do this FIRST — half of
   what looks like damage is a fingerprint from years in a pocket.
2. Hold the rear window at an angle under a bright light and rotate it.
   Scratches are almost invisible face-on and obvious at a glancing angle.
3. Open any camera app and point it at a lit bulb from a few metres away,
   with the rest of the room dim. Damage that hides in daylight is
   unmissable here: streaks and haloes radiating from the light.
4. Take one frame of the actual scene you plan to watch, and look at it
   on the largest screen you own — not on the phone. A phone display
   flatters everything.
5. Only now check the front: can you read enough of it, and does it
   respond to touch, to get through a setup once?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step three is the whole test. If a phone passes step three, the rest of its cosmetic history is mostly irrelevant to this job.&lt;/p&gt;

&lt;h2&gt;
  
  
  An honest note about our own line
&lt;/h2&gt;

&lt;p&gt;The line we have repeated more than any other is that the broken old phone somebody was told to recycle still films better than a cheap camera. I still think it is broadly right, and it is true of the specific break that put most of those phones out of service — the front one.&lt;/p&gt;

&lt;p&gt;It is not true of all of them, and we have never said which. A phone with a chipped rear window will produce a worse picture than a cheap dedicated camera in exactly the situations you bought a camera for, and no software fixes it, ours included. Repeating a cheerful generalisation without the exception is how people end up disappointed by the right idea.&lt;/p&gt;

&lt;p&gt;The exception is one sentence long and it belongs next to the claim every time it is made: check the small window, not the big one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this list deliberately does not settle
&lt;/h2&gt;

&lt;p&gt;It does not tell you whether a given handset is fast enough, has enough storage, or will get warm where you want to put it. Those are real questions with real answers and they are not damage questions. This is only the triage for a device that has already been dropped, which is most of the devices anybody is considering for this.&lt;/p&gt;

&lt;p&gt;It also cannot tell you about corrosion, board-level damage, or anything else that lives under the case. Nobody can, from the outside. The honest handling of that is not a confident verdict but a placement decision: a device with an unknown internal history goes somewhere you will notice it stopping, not somewhere you are relying on it silently for months.&lt;/p&gt;

&lt;p&gt;Two questions usually come right after triage, once a handset has passed: whether to &lt;a href="https://dev.to/superfunicular/should-you-leave-the-sim-card-in-an-old-phone-security-camera-a-dual-sim-guide-for-offline-wi-fi-587c"&gt;leave the SIM card in an old phone security camera&lt;/a&gt;, and whether a local-only camera phone is &lt;a href="https://dev.to/superfunicular/is-my-phone-security-camera-exposed-to-the-internet-on-ipv6-a-local-only-no-cloud-check-for-jio-3idk"&gt;exposed to the internet on IPv6&lt;/a&gt; even when you never set up remote access. Both are worth answering before the device goes on the shelf.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do this week
&lt;/h2&gt;

&lt;p&gt;If there is a retired handset in the house you have been meaning to put to work, do step one and step three above tonight. Five minutes with a cloth and a lamp will tell you whether you have a good camera or a permanently hazy one, and it will tell you before you have chosen a spot, run a cable and started trusting the thing.&lt;/p&gt;

&lt;p&gt;More at &lt;a href="https://superfunicular.com" rel="noopener noreferrer"&gt;superfunicular.com&lt;/a&gt;, and the app is &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;referrer=utm_source%3Ddevto%26utm_medium%3Darticle%26utm_campaign%3D2026w39" rel="noopener noreferrer"&gt;Background Camera RemoteStream&lt;/a&gt; on Google Play.&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>hardware</category>
      <category>security</category>
    </item>
    <item>
      <title>The Loopback Line: Why a Phone Serving Its Own Camera Page Gets Fewer Browser APIs Than localhost</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Mon, 21 Sep 2026 07:18:34 +0000</pubDate>
      <link>https://dev.to/superfunicular/the-loopback-line-why-a-phone-serving-its-own-camera-page-gets-fewer-browser-apis-than-localhost-541h</link>
      <guid>https://dev.to/superfunicular/the-loopback-line-why-a-phone-serving-its-own-camera-page-gets-fewer-browser-apis-than-localhost-541h</guid>
      <description>&lt;p&gt;You set up an old Android phone as a camera. It records with the screen off, and it runs a small web server so you can open the picture in a browser on your laptop. You type &lt;code&gt;http://192.168.1.42:8080&lt;/code&gt;, the feed comes up, and everything works.&lt;/p&gt;

&lt;p&gt;Then you notice three things that don't.&lt;/p&gt;

&lt;p&gt;The page cannot keep your laptop screen awake while you watch. It cannot register a service worker, so it re-fetches its own shell every single time. And if you try to embed that feed in any dashboard you host over HTTPS, the frame stays empty — not slow, not broken, &lt;em&gt;empty&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;None of these are bugs in the server. They are not bugs in the browser either. They are all the same decision, made once, in a specification that never mentions your phone, your network, or private IP addresses at all.&lt;/p&gt;

&lt;p&gt;I went looking for the sentence that causes it. The interesting part turned out to be a sentence that isn't there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The line itself
&lt;/h2&gt;

&lt;p&gt;The W3C &lt;a href="https://www.w3.org/TR/secure-contexts/" rel="noopener noreferrer"&gt;Secure Contexts&lt;/a&gt; specification defines whether an origin is "potentially trustworthy." Browsers use that one boolean to gate a large set of web APIs. The algorithm is short. In order, an origin is trustworthy if:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Its scheme is &lt;code&gt;https&lt;/code&gt; or &lt;code&gt;wss&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Its host matches the CIDR notations &lt;code&gt;127.0.0.0/8&lt;/code&gt; or &lt;code&gt;::1/128&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Its host is &lt;code&gt;localhost&lt;/code&gt;, &lt;code&gt;localhost.&lt;/code&gt;, or ends in &lt;code&gt;.localhost&lt;/code&gt; / &lt;code&gt;.localhost.&lt;/code&gt; — but only &lt;em&gt;"If the user agent conforms to the name resolution rules in [let-localhost-be-localhost]."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Its scheme is &lt;code&gt;file&lt;/code&gt; (a SHOULD, not a MUST).&lt;/li&gt;
&lt;li&gt;Its scheme is one the user agent considers authenticated, such as &lt;code&gt;chrome-extension:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It &lt;em&gt;"has been configured as a trustworthy origin."&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Otherwise: &lt;code&gt;Not Trustworthy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Two details in that list are worth slowing down for, because most summaries get them wrong.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;loopback CIDR is unconditional&lt;/strong&gt;. &lt;code&gt;127.0.0.1&lt;/code&gt; is trustworthy, full stop. The &lt;strong&gt;name &lt;code&gt;localhost&lt;/code&gt; is not&lt;/strong&gt; — it depends on the user agent following particular name-resolution rules, and §5.2 softens it further to a MAY. People say "localhost is a secure context" as if the two were the same rule. They aren't.&lt;/p&gt;

&lt;p&gt;And the spec is explicit that the usual levers don't apply: &lt;em&gt;"Neither origin's domain nor port has any effect on whether or not it is considered to be a secure context."&lt;/em&gt; Moving your server from 8080 to 8443 changes nothing. It was never about the port.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sentence that isn't there
&lt;/h2&gt;

&lt;p&gt;Here is the part I actually went to check, because I expected to find a carve-out and an argument about why it was narrow.&lt;/p&gt;

&lt;p&gt;There is no carve-out. There is no argument.&lt;/p&gt;

&lt;p&gt;I searched the Secure Contexts document for &lt;code&gt;192.168&lt;/code&gt;, &lt;code&gt;10.0.0.0&lt;/code&gt;, &lt;code&gt;RFC1918&lt;/code&gt;, "private IP", "private network", "intranet", and &lt;code&gt;169.254&lt;/code&gt;. &lt;strong&gt;Every one of them returns zero occurrences.&lt;/strong&gt; The only CIDR notations in the entire specification are &lt;code&gt;127.0.0.0/8&lt;/code&gt; and &lt;code&gt;::1/128&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Private network addresses are not excluded by a rule. They simply fall off the end of the algorithm into its final step, &lt;code&gt;Not Trustworthy&lt;/code&gt;, alongside every plain-HTTP address on the public internet. The spec does not discuss them, does not note them as a known gap, and does not leave an issue open about them.&lt;/p&gt;

&lt;p&gt;The one remaining route is §7.2, and it is a manual one:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"In order to support developers who run staging servers on non-loopback hosts, the user agent MAY allow users to configure specific sets of origins as trustworthy"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is a per-user, per-browser, per-machine setting intended for development. It is not something a device on your network can earn, negotiate, or opt into. Every person who ever opens the page would have to set it themselves, in their own browser.&lt;/p&gt;

&lt;p&gt;So there is a line, and it runs in a strange place. I've started calling it &lt;strong&gt;the loopback line&lt;/strong&gt;: the boundary between a server talking to itself and the same server talking to the machine next to it.&lt;/p&gt;

&lt;p&gt;A phone that serves its camera page &lt;em&gt;to itself&lt;/em&gt; is on the trusted side. The instant that identical page — same code, same server, same process, same device — is served to a laptop one hop away, it lands on the untrusted side. Nothing about the software changed. The only thing that changed is that the bytes left the device.&lt;/p&gt;

&lt;p&gt;Which is, of course, the entire point of a camera.&lt;/p&gt;

&lt;h2&gt;
  
  
  What lands on the untrusted side of the line
&lt;/h2&gt;

&lt;p&gt;"Not a secure context" is abstract until you list what it costs. MDN maintains the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Secure_Contexts/features_restricted_to_secure_contexts" rel="noopener noreferrer"&gt;list of features restricted to secure contexts&lt;/a&gt;. For a LAN camera page, these are the ones that bite:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service workers.&lt;/strong&gt; Gone. The Secure Contexts spec is blunt: &lt;em&gt;"Only secure contexts may register them."&lt;/em&gt; No offline shell, no cached UI, no graceful behaviour when the phone briefly drops off Wi-Fi. Every load is a cold load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notifications.&lt;/strong&gt; Gone. The viewer page cannot raise a desktop notification, which rules out a whole category of "tell me when the feed drops" built in the page itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;crypto.subtle&lt;/code&gt;.&lt;/strong&gt; Gone — and here is a precision worth keeping, because it's easy to overclaim in either direction. "Web Crypto needs HTTPS" is too broad: &lt;code&gt;crypto.getRandomValues()&lt;/code&gt; carries no secure-context requirement and keeps working. But don't under-claim either — both &lt;code&gt;crypto.subtle&lt;/code&gt; and &lt;code&gt;crypto.randomUUID()&lt;/code&gt; are marked &lt;code&gt;[SecureContext]&lt;/code&gt; in the Web Cryptography IDL, so random UUIDs go with the subtle interface, not with &lt;code&gt;getRandomValues()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;getUserMedia()&lt;/code&gt;.&lt;/strong&gt; Gone. MDN lists it separately from the main table, under methods that &lt;em&gt;"require a secure context (even if the associated API does not)."&lt;/em&gt; So the LAN page cannot open a camera of its own — relevant the moment you imagine two-way anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Screen Wake Lock.&lt;/strong&gt; Gone. And this is the one I keep turning over.&lt;/p&gt;

&lt;p&gt;The Screen Wake Lock API is how a web page asks the browser not to let the display sleep. It exists almost entirely for pages you watch without touching: recipes, dashboards, sheet music, live feeds. It is precisely, exactly the API a camera viewer wants.&lt;/p&gt;

&lt;p&gt;A LAN camera page cannot have it. The page whose entire job is to stay visible is denied the one API about staying visible.&lt;/p&gt;

&lt;p&gt;There's a symmetry here that I find funny, in a bleak way. On the recording end, the thing that makes screen-off capture work at all is an Android &lt;strong&gt;partial wake lock&lt;/strong&gt; held by a foreground service — keep the CPU running, let the display die. The viewer end has its own fight over attention, which I've written about separately: &lt;a href="https://dev.to/superfunicular/your-camera-tab-is-not-a-monitoring-session-how-chrome-throttles-freezes-and-discards-the-page-5cmi"&gt;what Chrome does to a camera tab you walk away from&lt;/a&gt; — throttled, then frozen, then discarded.&lt;/p&gt;

&lt;p&gt;The recorder fights to keep the CPU awake while the screen sleeps. The viewer would like to keep the screen awake so the tab is never backgrounded in the first place — and is told it hasn't earned the right to ask.&lt;/p&gt;

&lt;p&gt;Two wake locks, opposite goals, and only one of them is available to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mixed content, and the trap in the middle of it
&lt;/h2&gt;

&lt;p&gt;The second symptom — the empty iframe — is a different mechanism with the same root.&lt;/p&gt;

&lt;p&gt;If you serve any page over HTTPS and it tries to pull a subresource over plain HTTP, that's mixed content. Current browser behaviour splits it into &lt;strong&gt;upgradable&lt;/strong&gt; and &lt;strong&gt;blockable&lt;/strong&gt; content. Scripts, &lt;code&gt;fetch()&lt;/code&gt;, &lt;code&gt;XMLHttpRequest&lt;/code&gt;, stylesheets, fonts, &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt;, &lt;code&gt;sendBeacon&lt;/code&gt; and &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; sources are all blockable — they fail, they are not retried over HTTP.&lt;/p&gt;

&lt;p&gt;Images, audio and video are the &lt;em&gt;upgradable&lt;/em&gt; category. The browser rewrites the request to HTTPS and tries again. Which sounds like a loophole: serve an MJPEG snapshot as an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; and let it upgrade.&lt;/p&gt;

&lt;p&gt;It doesn't work, and the reason is a carve-out that's easy to miss. From MDN's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Mixed_content" rel="noopener noreferrer"&gt;mixed content&lt;/a&gt; page:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Mixed content requests that would otherwise be upgraded are blocked if the URL's host is an IP address rather than a domain name."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An upgrade to HTTPS only makes sense if there's a name that could plausibly have a certificate. &lt;code&gt;192.168.1.42&lt;/code&gt; is an IP literal, so &lt;code&gt;&amp;lt;img src="http://192.168.1.42/snapshot.jpg"&amp;gt;&lt;/code&gt; on an HTTPS page is &lt;strong&gt;blocked, not upgraded&lt;/strong&gt;. The category that was supposed to be the lenient one is, for your camera specifically, the strict one.&lt;/p&gt;

&lt;p&gt;One piece of vocabulary, since the old term is still repeated as though it were current. The upgradable category used to be called &lt;em&gt;optionally-blockable&lt;/em&gt;. Both the &lt;a href="https://www.w3.org/TR/mixed-content/" rel="noopener noreferrer"&gt;Level 1 Candidate Recommendation&lt;/a&gt; and &lt;a href="https://w3c.github.io/webappsec-mixed-content/level2.html" rel="noopener noreferrer"&gt;Level 2&lt;/a&gt; now use the newer &lt;em&gt;upgradeable&lt;/em&gt; wording, and note that it &lt;em&gt;"was previously referred to as optionally-blockable"&lt;/em&gt; in earlier versions. So if you find a source leaning on "optionally-blockable" as live terminology, it predates that change — the behaviour it describes is the same, the name isn't.&lt;/p&gt;

&lt;p&gt;And a confirmed absence, because I looked: Mixed Content Level 2 contains &lt;strong&gt;zero occurrences&lt;/strong&gt; of the word "iframe." It reaches iframes through its algorithm — it permits a request whose &lt;em&gt;"destination is 'document', and request's target browsing context has no parent browsing context"&lt;/em&gt;, i.e. top-level navigations only. A framed document falls through to blocked. MDN says "iframes are blocked" in plain words; the spec never does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What replaced the fix everyone was waiting for
&lt;/h2&gt;

&lt;p&gt;For a few years the expected fix for all of this was &lt;strong&gt;Private Network Access&lt;/strong&gt; — a scheme where a public page wanting to reach a private address would send a CORS preflight carrying &lt;code&gt;Access-Control-Request-Private-Network: true&lt;/code&gt;, and the local device would answer with &lt;code&gt;Access-Control-Allow-Private-Network: true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Two corrections, because I nearly wrote this section as current behaviour and it isn't.&lt;/p&gt;

&lt;p&gt;First, &lt;a href="https://wicg.github.io/private-network-access/" rel="noopener noreferrer"&gt;PNA&lt;/a&gt; is a WICG Draft Community Group Report. In its own words: &lt;em&gt;"It is not a W3C Standard nor is it on the W3C Standards Track."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Second, and more importantly: &lt;strong&gt;Chrome does not enforce it.&lt;/strong&gt; From Chrome's own &lt;a href="https://developer.chrome.com/blog/pna-on-hold" rel="noopener noreferrer"&gt;PNA on hold&lt;/a&gt; post, published October 2024: &lt;em&gt;"PNA preflights are not currently enforced,"&lt;/em&gt; the Chrome 130 rollout having been halted over compatibility problems. Anything you read describing that preflight as live browser behaviour is out of date.&lt;/p&gt;

&lt;p&gt;What replaced it is &lt;a href="https://developer.chrome.com/blog/local-network-access" rel="noopener noreferrer"&gt;Local Network Access&lt;/a&gt; — &lt;em&gt;"Local Network Access replaces that effort, after PNA was put on hold."&lt;/em&gt; That post went up in June 2025 and now carries an update saying the permission prompt is launching in Chrome 142. It is a permission prompt rather than a preflight, so no &lt;code&gt;Access-Control-Request-Private-Network&lt;/code&gt; header is involved at all.&lt;/p&gt;

&lt;p&gt;Now look at the shape of it, because the shape is the whole story. LNA is a permission that a page asks for &lt;strong&gt;in order to reach into&lt;/strong&gt; your local network. And &lt;em&gt;"the ability to request this permission is restricted to secure contexts."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So the direction of travel is: an HTTPS page, already trusted, may ask your permission to reach your camera. Your camera's own page, serving from your own network, gains nothing. It is still not a secure context, still cannot register a service worker, still cannot hold a screen wake lock.&lt;/p&gt;

&lt;p&gt;The platform is building a door for traffic coming &lt;em&gt;in&lt;/em&gt; from the public web. It is not building one for a device on your LAN that wants to be trusted by the machine next to it. If anything, the asymmetry is widening: the capability now flows toward origins that already have certificates.&lt;/p&gt;

&lt;p&gt;(This is the browser's half of the story. The operating system has its own, separate story about apps reaching LAN devices — different mechanism, different gate, and not what any of the above describes.)&lt;/p&gt;

&lt;h2&gt;
  
  
  So why not just serve HTTPS?
&lt;/h2&gt;

&lt;p&gt;Because the certificate model and a phone on your living-room Wi-Fi were designed for different worlds, and a public CA will not issue a certificate for a private IP address. I've written that argument out properly in &lt;a href="https://dev.to/superfunicular/local-only-is-not-the-same-as-private-the-lan-threat-model-for-a-phone-as-camera-server-4jpi"&gt;the LAN threat model for a phone-as-camera server&lt;/a&gt;, including why a self-signed certificate trades one problem for a worse habit, so I won't re-run it here.&lt;/p&gt;

&lt;p&gt;The relevant point for this article is narrower: even if you solved the transport question, you would be solving it to recover browser APIs, not to protect an already-local link. That's a strange thing to spend a user's trust on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The design consequence
&lt;/h2&gt;

&lt;p&gt;Once you accept that the viewer page lives permanently on the untrusted side of the loopback line, a lot of architectural decisions stop being decisions.&lt;/p&gt;

&lt;p&gt;You build the console as a &lt;strong&gt;self-contained page with no secure-context dependencies&lt;/strong&gt;. No service worker, so no offline shell — the page has to be small enough that a cold load is cheap. No wake lock, so if a user wants the screen to stay on while they watch, that's a setting on their own device, and the honest thing is to say so rather than to ship a button that silently fails. No notifications from the page, so status has to be visible &lt;em&gt;in&lt;/em&gt; the page.&lt;/p&gt;

&lt;p&gt;And the transport has to be something a plain, unprivileged browser context does natively and well: direct HTTP, an MJPEG or similar stream for live view, and ordinary byte-range requests for recorded files. That last one is less boring than it sounds — &lt;a href="https://dev.to/superfunicular/the-range-header-is-the-whole-feature-serving-recorded-video-from-a-phones-own-web-server-3hje"&gt;the Range header does most of the work of seeking in a recording&lt;/a&gt;, which is exactly the kind of capability that survives on the untrusted side because it was never gated in the first place. The embedded-server side of this, on Ktor, I've &lt;a href="https://dev.to/superfunicular/how-an-android-phone-serves-its-own-live-camera-feed-over-your-lan-an-embedded-ktor-server-30n9"&gt;taken apart separately&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The result looks austere next to a cloud camera's web app. That austerity isn't a shortcut. It's the shape of what remains after you remove everything a non-secure context isn't allowed to touch.&lt;/p&gt;

&lt;p&gt;This is the architecture behind &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam" rel="noopener noreferrer"&gt;Background Camera RemoteStream&lt;/a&gt; — an Android app that records with the screen off and serves its own feed over your LAN from a built-in web server, with no cloud account in the path. The design constraints above are not incidental to that; they're most of why the viewer looks the way it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest trade
&lt;/h2&gt;

&lt;p&gt;A vendor camera with a cloud dashboard has none of these problems, and it's worth being clear about why: their dashboard is served from a domain they own, over HTTPS, with a certificate they renew. It's a secure context. It gets service workers, notifications, wake lock, the lot. That's a real advantage and there's no point pretending otherwise.&lt;/p&gt;

&lt;p&gt;What it costs is that the picture goes to their server so that their page can be trusted by your browser. The trust is real, and it's rented.&lt;/p&gt;

&lt;p&gt;A phone on your own network keeps the picture where it is and pays for it in browser capabilities — a page that must be simple, stateless between loads, and unable to ask your laptop for much of anything.&lt;/p&gt;

&lt;p&gt;I don't think that's a bad trade. But I'd rather explain it as a trade than let someone discover it as a series of small unexplained failures, which is how almost everyone meets the loopback line for the first time.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Background Camera RemoteStream&lt;/strong&gt; — record with the screen off, stream to YouTube Live, view remotely over your LAN from a built-in web server, with local-only storage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Play: &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=com.superfunicular.digicam&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Site: &lt;a href="https://superfunicular.com" rel="noopener noreferrer"&gt;https://superfunicular.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Specification text quoted above was read from the linked primary sources: W3C Secure Contexts, W3C Mixed Content Level 2, the WICG Private Network Access draft, MDN, and Chrome's developer blog. Where a document is a draft rather than a standard, I've said so inline, because the status turned out to matter more than once.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>webdev</category>
      <category>security</category>
      <category>privacy</category>
    </item>
    <item>
      <title>The Offence Is the Listening, Not the Recording: A Real Estate Commission's Own Answer on Cameras During a Showing</title>
      <dc:creator>Super Funicular</dc:creator>
      <pubDate>Mon, 21 Sep 2026 06:56:11 +0000</pubDate>
      <link>https://dev.to/superfunicular/the-offence-is-the-listening-not-the-recording-a-real-estate-commissions-own-answer-on-cameras-23k8</link>
      <guid>https://dev.to/superfunicular/the-offence-is-the-listening-not-the-recording-a-real-estate-commissions-own-answer-on-cameras-23k8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; The federal wiretap chapter defines its central verb around acquiring a conversation, not around saving one. A state licensing regulator has published what that means for a house on the market: a seller may run video with the microphone off, and a seller who listens live has intercepted the conversation even where no file was produced. Switching off recording is a smaller fix than it sounds, because it is aimed at the wrong half of the device.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A spare handset running as a camera is set up for an empty house. That is the assumption underneath most advice about it: nobody is home, the interesting event is an intrusion, and the useful output is a file you look at afterwards.&lt;/p&gt;

&lt;p&gt;Putting the house on the market inverts each of those in the same week. The house is occupied, by appointment, by people the owner has not met. The owner is the one who is out. And the interesting event is no longer an intrusion; it is two people walking from room to room talking to each other about the place, and about what they might pay for it. The camera has not changed. Everything around it has.&lt;/p&gt;

&lt;p&gt;Two documents carry most of the weight here, and they point the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The federal definition is built around acquisition, not storage
&lt;/h2&gt;

&lt;p&gt;The definitions section of the federal wiretap chapter, 18 U.S.C. § 2510, says that to intercept means "the aural or other acquisition of the contents of any wire, electronic, or oral communication through the use of any electronic, mechanical, or other device."&lt;/p&gt;

&lt;p&gt;Read the first four words before the rest of it. &lt;em&gt;Aural acquisition.&lt;/em&gt; Hearing is a way of acquiring. There is no mention of a file, a copy, a disk, a retention period, or a duration. The verb the whole chapter is built on describes something that is finished at the moment a person understands what was said.&lt;/p&gt;

&lt;p&gt;The word order is not an accident of drafting, and the statute's own amendment history says so. As enacted in 1968 the definition read &lt;em&gt;aural acquisition&lt;/em&gt; and stopped there. The words &lt;em&gt;or other&lt;/em&gt; were inserted eighteen years later, by the Electronic Communications Privacy Act of 1986, in the same amendment that added &lt;em&gt;electronic&lt;/em&gt; to the list of communications it covers. Hearing was not one option among several that a later Congress trimmed down to. Hearing was the whole of it, and the rest was added on top. The findings published with the 1968 Act use the plainer word: intercepting devices, Congress wrote there, were being used "to overhear oral conversations made in private".&lt;/p&gt;

&lt;p&gt;The definition of the &lt;em&gt;device&lt;/em&gt; that does the acquiring is drawn just as wide, which you can tell from what had to be written out of it. The list of things that are excluded runs to ordinary telephone equipment used in the ordinary course of business, and then to "a hearing aid or similar device being used to correct subnormal hearing to not better than normal". Congress had to carve out a hearing aid. That is the size of the net a drafter thought they were casting, and a phone on a shelf sits well inside it.&lt;/p&gt;

&lt;p&gt;None of that makes hearing your visitors unlawful on its own. The chapter turns on consent, and state statutes differ in how many parties have to agree; the one below describes its own Act as requiring the consent of at least one party to the conversation. The question is therefore not whether a device recorded. It is whether the person listening was a party, or had a party's agreement.&lt;/p&gt;

&lt;h2&gt;
  
  
  A licensing regulator answers the question directly
&lt;/h2&gt;

&lt;p&gt;The North Carolina Real Estate Commission is the body that issues and removes the licences of brokers in that state, so its bulletins are written to be followed rather than debated. In a September 2023 bulletin for brokers, it walks through the federal prohibition at 18 U.S.C. § 2511 and notes, in its own words, that "This federal statute also prohibits the interception of oral communication, whether it is recorded or not." It then adds the carve-out that the rest of the piece depends on: a person is not in breach where state law permits hearing an oral communication and a party to the conversation has consented.&lt;/p&gt;

&lt;p&gt;Then it asks the question a seller would ask, and answers it without hedging. Is it permissible for a seller to either listen to or record a conversation between a potential buyer and their agent?&lt;/p&gt;

&lt;p&gt;"No. It is not permissible for a seller to listen in or record a conversation between a potential buyer and their agent because the seller is not a party to the conversation and they have not obtained the written consent of one of the parties."&lt;/p&gt;

&lt;p&gt;The reasoning is the part worth carrying away, because it survives the trip to other states even though the conclusion might not. The seller is absent from the conversation. The seller is therefore not the party whose consent a one-party state would accept. And the buyer's own agent, who &lt;em&gt;is&lt;/em&gt; a party, has not been asked. A statute that would have been satisfied by one person in the room agreeing is left with nobody who agreed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sentence that reaches a phone
&lt;/h2&gt;

&lt;p&gt;The bulletin then does something documents of its kind mostly avoid. It names hardware:&lt;/p&gt;

&lt;p&gt;"Although baby monitors and walkie-talkies do not record the conversation, the conversation is still being intercepted by the seller without the consent of the parties."&lt;/p&gt;

&lt;p&gt;The bulletin has just told brokers that sellers should not use non-recording audio devices like walkie-talkies or baby monitors. A baby monitor stores nothing. A walkie-talkie stores nothing. They are named anyway, because the thing the statute describes has already happened by the time the sound reaches a speaker somewhere else.&lt;/p&gt;

&lt;p&gt;That sentence is written about a nursery gadget from a previous decade, and it lands on a category of software feature that did not exist when the gadget did. A live view with sound, a listen button, a talk-back channel, a remote stream you can hear as well as see: whatever a given app calls it, the described behaviour is the same one. Sound leaves a room the owner is not standing in and arrives somewhere the owner is. The bulletin does not have to mention phones to have described what a phone does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The video half is left standing
&lt;/h2&gt;

&lt;p&gt;This is not an argument for taking the camera down, and the Commission's own answer to the video question is yes, with conditions: "the seller should exercise caution regarding the placement of the device to ensure a person's privacy is not violated and the audio is turned off". Its own summary of the state Electronic Surveillance Act is that the Act is addressed to oral and electronic communications rather than to video surveillance, which is why the two halves of the same handset land in different places.&lt;/p&gt;

&lt;p&gt;The conditions are not decorative. Placement is doing real work in that sentence, and the bulletin gives the obvious example of a room a camera has no business pointing into, a bathroom. It also warns brokers that a seller who tries to gather confidential information about a buyer by listening to their conversation is exposed to criminal or civil liability, which is a different and larger hazard than a tidy question about consent.&lt;/p&gt;

&lt;p&gt;And the Commission goes further than the conclusion this piece is heading for. Having said that video without audio is permissible, it recommends that brokers advise their sellers not to use any device as a means to attempt to gain information about potential buyers or their agents. That is a recommendation about the purpose the hardware is put to, not about which of its two inputs is switched on, and it is wider than the fix described below. It should be said plainly rather than left out: the regulator's advice goes past the line this piece stops at.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the obvious fix is the wrong one
&lt;/h2&gt;

&lt;p&gt;Somebody who has read this far and is selling a house will reach for the same control that everyone reaches for. Turn off recording. Keep the live view so the house is still watched, and stop writing files while strangers are inside.&lt;/p&gt;

&lt;p&gt;On the reading above, that control is pointed at the wrong half. It stops the artefact and leaves the acquisition running. The federal definition is satisfied by the aural acquisition itself, and the bulletin says out loud that a device which stores nothing is still intercepting. A setting that makes the evidence disappear and leaves the conduct in place is worse than no setting at all, because it feels like having done something.&lt;/p&gt;

&lt;p&gt;The control that matches the documents is the microphone, and it is a different switch. Sound off, video on, and the two halves of the handset are once again in the two different places the Act puts them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not settle
&lt;/h2&gt;

&lt;p&gt;One state's regulator reading one state's statute is not a national rule, and it would be dishonest to present it as one. The federal chapter is generally read as a floor that a state may build on, and states differ on how many parties to a conversation have to agree before somebody else may listen. The definition of an oral communication in the federal chapter itself turns on whether the speaker was exhibiting an expectation that the words would not be intercepted, and under circumstances that justify it, which is a question about the room rather than about the statute.&lt;/p&gt;

&lt;p&gt;What travels is the distinction, not the verdict. Wherever you are, the question the documents ask is who was party to the conversation, and the question they do not ask is whether a file exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read the two halves of the handset as two different legal objects, because that is what the documents do. We have made the same split from the Android side, where the camera and the microphone are separate permissions and the audio one is the stricter: &lt;a href="https://dev.to/superfunicular/every-guide-to-running-a-phone-as-a-camera-says-grant-camera-and-microphone-only-one-of-those-is-dio"&gt;why the microphone is a different permission from the camera&lt;/a&gt;. What is new here is the direction of travel. That piece reasons outwards from the operating system; a regulator writing about somebody's living room arrives at the same line inwards from a statute.&lt;/li&gt;
&lt;li&gt;The consent count is a state-by-state fact, and it is the fact everything above turns on. Settle it before a showing is booked rather than during one, and settle it from a real estate commission bulletin rather than a forum, because a regulator publishes what it is prepared to act on.&lt;/li&gt;
&lt;li&gt;Tell the listing agent, in writing, what devices are on the property and where they point. The agent has professional exposure of their own here, and a written note converts a surprise into a disclosure.&lt;/li&gt;
&lt;li&gt;Point the lens where the people you meant to watch would actually be. The doors and the perimeter were the reason the camera went up; the room where two visitors stand talking was not.&lt;/li&gt;
&lt;li&gt;Resist watching a showing live. The temptation is the point of the feature, and it is also the conduct the bulletin describes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I could not verify
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Whether any enforcement has actually followed from a seller listening during a showing. I found the regulator's position; I did not find a disciplinary case turning on it, and I would rather record the gap than imply a body of precedent I did not read.&lt;/li&gt;
&lt;li&gt;How the other states come out. I read one state's regulator and the federal definitions section, and I did not work through the rest. I am not going to point you at a survey I have not opened.&lt;/li&gt;
&lt;li&gt;Whether a house being shown commercially weakens the expectation of privacy that the federal definition of an oral communication rests on. It is the obvious counter-argument to everything above, the text does not resolve it, and I found nothing that settled it either way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is legal advice and I am not a lawyer. It is a reading of two public documents, aimed at people whose camera happens to be a phone and who are about to let strangers walk past it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://play.google.com/store/apps/details?id=com.superfunicular.digicam&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=2026w39" rel="noopener noreferrer"&gt;Background Camera RemoteStream on Google Play&lt;/a&gt; -- record with the screen off, keep footage on the device, watch it over your own network. More of these readings live at &lt;a href="https://superfunicular.com" rel="noopener noreferrer"&gt;notes on running an old phone as a camera&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources.&lt;/strong&gt; &lt;a href="https://bulletins.ncrec.gov/tech-corner-the-use-of-audio-and-video-equipment-during-showings-whos-listening/" rel="noopener noreferrer"&gt;the North Carolina Real Estate Commission on audio and video equipment during showings&lt;/a&gt;, and &lt;a href="https://www.law.cornell.edu/uscode/text/18/2510" rel="noopener noreferrer"&gt;the definitions section of the federal wiretap chapter on Cornell LII&lt;/a&gt;. Quotations from the definitions section are verbatim statutory text as published, and the 1986 insertion of &lt;em&gt;or other&lt;/em&gt; and the 1968 congressional findings are quoted from the editorial and statutory notes on that same page; quotations from the bulletin are the Commission's own words, including its answers to its own questions. Consent is the hinge, and it swings on whether anyone in that room grasped that somebody outside it was within earshot.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>android</category>
      <category>security</category>
      <category>legal</category>
    </item>
  </channel>
</rss>
