Reveal hidden cameras and surveillance devices — and understand what a scan can and cannot prove.
Hidden-camera abuse (in Korea it has a name — molka, 몰카) has become a serious problem in hotels, Airbnbs, changing rooms, restrooms and rentals across Asia and beyond. Argus is an honest, auditable tool that helps ordinary people find hidden cameras — and, just as importantly, tells you the limits of what it finds so you are never given false confidence.
It is a five-layer toolkit: a network scanner, an optical-sweep phone app, a nearby-WiFi airwaves sweep, a raw-802.11 capture analyser, and a self-device audit — every layer passive and defensive (it listens; it never attacks). See the layer table below. The fastest way to see it work with no setup:
python -m argus.monitor --demo # sample capture: finds a hidden AP + a client-camera _ ___ ___ _ _ ___
/_\ | _ \ __| | | / __| counter-surveillance · layer 1: network sweep
/ _ \| / _|| |_| \__ \ reveals WiFi / IP cameras + DVRs on this network
/_/ \_\_|_\___|\___/|___/
Each way a camera (or spyware) gives itself away maps to a layer. Every layer is passive — it listens, fingerprints, and explains; it never attacks.
flowchart TD
HC["Hidden camera"]
SW["Spyware on your own device"]
HC -->|"on your WiFi"| L1["Layer 1: Network scan"]
HC -->|"a nearby access point"| L3["Layer 3: Airwaves sweep"]
HC -->|"hidden AP / client on a network"| L3B["Layer 3b: Monitor capture"]
HC -->|"lens glint or night-vision IR"| L2["Layer 2: Optical sweep (phone)"]
SW -->|"uses your camera or mic"| L4["Layer 4: Self-device audit"]
L1 --> R["Ranked, explained findings - with honest limits"]
L2 --> R
L3 --> R
L3B --> R
L4 --> R
No single layer is enough on its own, and the tool says so: a clean result in one layer never means "you are safe." Coverage comes from running the layers together.
When you run a scan, Argus:
- Discovers every device on your current network (concurrent ping sweep + ARP-cache harvesting for MAC addresses — no admin rights required).
- Listens for camera announcement protocols that cameras speak natively:
- ONVIF WS-Discovery — the industry camera standard. Anything that answers
as a
NetworkVideoTransmitteris, by definition, a camera/encoder. - SSDP / UPnP — many cameras and DVRs announce themselves here.
- mDNS / Bonjour — cameras advertise
_rtsp._tcp,_onvif._tcp,_axis-video._tcpand friends. - Reverse-DNS hostnames — names like
IPC-3A1F,living-room-cameraorreolink-doorbellare often the most revealing clue of all.
- ONVIF WS-Discovery — the industry camera standard. Anything that answers
as a
- Fingerprints open services on each device — a polite TCP connect scan of
camera/DVR ports, then active probes:
- HTTP/HTTPS — reads the
Serverheader, Basic-auth realm and page title, which very often name the device ("Hikvision", "NETSurveillance", …). - RTSP
OPTIONS— a device that answers RTSP is streaming video. Ordinary PCs and phones do not run RTSP servers.
- HTTP/HTTPS — reads the
- Identifies the vendor two independent ways: behavioral signatures (what the device says it is) and MAC OUI (who made it).
- Scores the risk with transparent rules and prints, for every flagged device, the exact reasons it was flagged — never a black-box verdict.
- Standard library only. The scanner core has zero third-party dependencies — a counter-surveillance tool must be auditable end-to-end and must not phone home. It only talks to your local network.
- Behavior over guessing. Live ONVIF/RTSP responses outweigh MAC-vendor guesses, so detection does not hinge on an always-incomplete OUI database.
- Never say "you're safe." A clean network scan does not mean a room is clean. Argus always prints what it cannot see (see below).
No dependencies needed for the core scan. Python 3.10+.
git clone <your-fork-url> argus
cd argus
python -m argus # scan your current /24Optional, for development:
pip install -e ".[dev]" # pytest etc.
pytest # run the test suite# Scan the network you are currently connected to
python -m argus
# Scan a specific subnet you control
python -m argus 192.168.1.0/24
# Be thorough: probe every address (catches cameras that ignore ping),
# the full camera/DVR port list, and save machine-readable results
python -m argus --thorough --full-ports --json scan.json
# Layer 3 — airwaves: list every WiFi access point AROUND you, flag cameras
python -m argus.airwaves
python -m argus.airwaves --locate AA:BB:CC:DD:EE:FF # walk toward a flagged AP
# Layer 3b — monitor capture: find hidden APs + client-cameras from a capture
python -m argus.monitor --demo # see it work on a sample
python -m argus.monitor --read capture.pcap # analyse a real monitor-mode capture
# Layer 4 — self-device audit: is something watching through YOUR camera?
python -m argus.selfaudit # who's used your webcam/mic, spyware checkUseful flags:
| Flag | Meaning |
|---|---|
--thorough |
Port-scan every address, not just hosts that answered ping |
--full-ports |
Probe the full camera/DVR port list (slower) |
--watch [SECS] |
Re-scan every SECS (default 30) and alert on NEW cameras that appear — catches devices powered on after you arrive |
--udp-wait N |
Seconds to listen for ONVIF/SSDP/mDNS replies (default 3) |
--json PATH |
Write JSON results (- for stdout) |
--strict |
Exit code 1 if a likely camera is found (for automation) |
--no-mdns / --no-hostname |
Skip mDNS discovery / reverse-DNS lookups |
--no-color |
Plain output |
--force |
Allow scanning a non-private range (use responsibly) |
OK No networked cameras detected on this subnet
+- 192.168.1.7 - TP-Link
| iot device mac 5C:62:8B:49:4F:D0 via arp,ping
| risk ##.................. 8/100
| ports 80(http)
| [LOW ] MAC vendor also makes cameras: TP-Link
+-
A likely camera looks like this:
[!] 1 LIKELY CAMERA/DVR DEVICE(S) FOUND
+- 192.168.1.64 - Hikvision
| likely camera / DVR mac 44:19:B6:.. via onvif,arp,ping
| risk #############....... 62/100
| [CRIT] ONVIF camera responding (NetworkVideoTransmitter)
| [HIGH] Live RTSP video service
+-
This is the most important section. A clean result does not mean the room is clean. A network sweep only sees devices on the WiFi/LAN you are on. It cannot see:
- cameras recording to a local SD card with no network connection;
- cameras on a separate / hidden WiFi or a 4G/5G SIM;
- analog / wired cameras and classic optical bugs;
- a device that is simply powered off at the moment you scan.
For those, you need the other layers (physical/optical/RF sweep). See
docs/THREAT_MODEL.md for the full, honest picture and
docs/SELF_DEVICE_CHECKLIST.md for the
"is someone watching through my own phone/laptop, even when it looks off?"
question.
Argus is designed as a layered counter-surveillance suite, mirroring how professional TSCM (technical surveillance counter-measures) sweeps actually work:
| Layer | Status | What it finds |
|---|---|---|
| 1. Network scan | ✅ / |
WiFi/IP cameras, DVRs, NVRs on the network you're joined to |
| 2. Optical sweep | ✅ /app |
hidden lenses via retro-reflection + night-vision IR LEDs, using a phone camera. Catches offline cameras a network scan can't. Installable PWA, on-device only. |
| 3. Airwaves sweep | ✅ argus.airwaves |
every WiFi access point around you (not just your network) — flags camera hotspots by vendor MAC, spy-cam SSID patterns, and hidden broadcast. Passive only. |
| 3b. Monitor capture | ✅ argus.monitor |
reads raw 802.11 from a monitor-mode capture (or live) to surface hidden APs and client-cameras — a camera that's a client on a network, invisible to every other scan. Headers only, never transmits. |
| 4. Self-device audit | ✅ argus.selfaudit |
whether your own device is watching you — who's used the webcam/mic (incl. right now), startup persistence, known-stalkerware processes, honest hardening guidance. Windows today; phones via the checklist doc. |
| 5. Physical methodology | ✅ docs | the human sweep checklist: where cameras hide, common concealment objects |
Layers 1 and 3 are complementary: Layer 1 scans the network you're on; Layer 3 listens to every network around you and flags the ones that are cameras. Neither attacks anything — a camera's radio presence reveals it without intrusion, which is both more reliable and legal. The optical sweep (Layer 2) is a cross-platform PWA for iPhone + Android; note that iPhone cannot do airwaves scanning (Apple blocks nearby-WiFi APIs), so Layer 3 runs on a laptop.
Argus is for defensive use: finding devices that violate your privacy in spaces you occupy, and auditing networks you own or are authorised to test.
- It refuses to scan non-private IP ranges unless you pass
--force. - It only scans the network you are connected to.
- A connect-scan + service probe is the same traffic a browser makes; it is not an exploit. Still: only scan networks you own or have permission to test.
- If you find a hidden camera in a rental or public space: do not confront anyone. Document it (photos), preserve evidence, and contact local police and the accommodation platform. In many countries covert recording in private spaces is a serious crime.
Everything that drives a verdict lives in plain, reviewable files:
argus/config.py— the ports and timing constants.argus/data/camera_ouis.csv— curated camera-vendor MAC prefixes.argus/data/vendor_signatures.json— behavioral fingerprints (precision-first).argus/scoring/rules.py— each detection rule, small and independently tested.argus/scoring/score.py— how findings become a 0–100 risk and a category.
Run pytest to see the detection logic exercised against captured camera and
router banners, including a regression test that pins a real false-positive
(a router whose Innbox_webserv banner must never be mistaken for a camera).
MIT — see LICENSE.