{"id":430,"date":"2026-03-24T02:18:45","date_gmt":"2026-03-24T02:18:45","guid":{"rendered":"http:\/\/quantusintel.group\/osint\/blog\/2026\/03\/24\/channel-monitor-gets-a-standalone-web-ui\/"},"modified":"2026-03-24T02:18:45","modified_gmt":"2026-03-24T02:18:45","slug":"channel-monitor-gets-a-standalone-web-ui","status":"publish","type":"post","link":"https:\/\/quantusintel.group\/osint\/blog\/2026\/03\/24\/channel-monitor-gets-a-standalone-web-ui\/","title":{"rendered":"Channel Monitor Gets a Standalone Web UI"},"content":{"rendered":"<figure><img data-opt-id=835908649  fetchpriority=\"high\" decoding=\"async\" alt=\"\" src=\"https:\/\/cdn-images-1.medium.com\/proxy\/1*1wh7AMlraxG2ZNKQb3kimg.png\" \/><\/figure>\n<p>If you have been following this series, you know the history. The first version was a command-line Python script\u200a\u2014\u200ayou ran it, it scraped a Telegram channel, translated everything, downloaded the media, and dropped a self-contained HTML report into an output folder. Useful, but you had to be comfortable with a terminal and you had to manage it yourself.<\/p>\n<p>The second version integrated that scraper directly into the threat intelligence dashboard which is a separate project and an overkill is the channel monitor is all that you are after. You got a full UI, live log streaming, job history, one-click ZIP downloads, all without touching a terminal.<\/p>\n<p>A few people reached out asking for something in between. They did not want the full platform which included the dark web crawler, the database, the Docker stack\u200a\u2014\u200athey just wanted the channel monitor. Standalone. With the UI. Deployable in five minutes on any Linux\u00a0machine.<\/p>\n<p>So that is what this\u00a0is.<\/p>\n<h3>What Is New\u200a\u2014\u200aStandalone Web\u00a0UI<\/h3>\n<p>The standalone version is a single Flask application. No Docker, no database, no platform dependencies. You clone the repo, run the installer, and you have a web interface running on port 5000. If you still want to use only the Shell based version, you can stick to the old one, the features are more or less the same, without the\u00a0UI.<\/p>\n<pre>git clone https:\/\/github.com\/osintph\/channel-monitor-ui.git<br \/>cd channel-monitor-ui<br \/>bash install.sh<br \/>sudo bash install-service.sh<\/pre>\n<p>That is it. The installer handles the virtual environment, dependencies, credential setup, and Telegram authentication in sequence. The service script registers it as a systemd unit so it starts on boot and runs in the background via Gunicorn.<\/p>\n<figure><img data-opt-id=771569372  fetchpriority=\"high\" decoding=\"async\" alt=\"\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*kTN-NYY0cgMPpy7JX3jvbg.png\" \/><\/figure>\n<h3>The Interface<\/h3>\n<p>The UI is deliberately simple. Left panel is the scan form. Right panel is the job list and live\u00a0log.<\/p>\n<figure><img data-opt-id=771569372  decoding=\"async\" alt=\"\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*5cQ3nTtP3-LotDNIDDxUug.png\" \/><\/figure>\n<p>You enter a channel username or full link, configure your options, and hit Start Scan. The same options from the CLI are all\u00a0here:<\/p>\n<ul>\n<li><strong>Message limit<\/strong>\u200a\u2014\u200ahow many messages to fetch, 0 for\u00a0all<\/li>\n<li><strong>Days back<\/strong>\u200a\u2014\u200arestrict to recent messages\u00a0only<\/li>\n<li><strong>Force language<\/strong>\u200a\u2014\u200askip per-message detection if you know the source\u00a0language<\/li>\n<li><strong>Max video size<\/strong>\u200a\u2014\u200acap video downloads or skip\u00a0entirely<\/li>\n<li><strong>Min free disk<\/strong>\u200a\u2014\u200aautomatic abort if disk space drops too\u00a0low<\/li>\n<li><strong>Skip English translation<\/strong>\u200a\u2014\u200aavoid unnecessary API calls on English\u00a0channels<\/li>\n<\/ul>\n<p>The live log streams in real time as the scan runs. Every message processed, every photo and video downloaded, every translation. You can leave the tab and come back\u200a\u2014\u200athe job keeps running in the background.<\/p>\n<p>When the scan completes the job card updates to COMPLETED and the download button\u00a0appears.<\/p>\n<figure><img data-opt-id=771569372  decoding=\"async\" alt=\"\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*0iczDmshFfIbYwPLRVmO0A.png\" \/><\/figure>\n<figure><img data-opt-id=771569372  decoding=\"async\" alt=\"\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*MHF4bjfRGhQNW50rA_OgIQ.png\" \/><\/figure>\n<h3>The Output<\/h3>\n<p>Nothing changed here from the integrated platform version. The ZIP contains the same three\u00a0things:<\/p>\n<p><strong>messages.html<\/strong>\u200a\u2014\u200aa self-contained report that opens directly in any browser. Original text in amber, right-to-left aligned where appropriate for Arabic and Farsi. English translation in green below. Photos rendered inline. Videos with an embedded player. Language badge on every message. No server required, you can attach it directly to a report or share it\u00a0as-is.<\/p>\n<p><strong>messages.json<\/strong>\u200a\u2014\u200araw structured data. Every message with its ID, timestamp, original text, translated text, detected language, media type, media path, view count, and reply chain. Pipe it into whatever analysis workflow you\u00a0have.<\/p>\n<p><strong>media\/<\/strong>\u200a\u2014\u200aall downloaded photos and videos named by message\u00a0ID.<\/p>\n<figure><img data-opt-id=771569372  decoding=\"async\" alt=\"\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*1wh7AMlraxG2ZNKQb3kimg.png\" \/><\/figure>\n<h3>Job History and Persistence<\/h3>\n<p>One thing that was missing in the integrated platform version\u200a\u2014\u200ajob history did not survive container restarts. That is fixed here. Every completed job is written to data\/jobs_index.json immediately on completion. When the service restarts, all previous jobs reload automatically. Your completed scans, their logs, and their download links are all still\u00a0there.<\/p>\n<p>I recorded this short Video of an end to end process, sorry for the sound quality and low resolution but you get the idea\u00a0\ud83d\ude00<\/p>\n<p><a href=\"https:\/\/medium.com\/media\/e78f20d4b9370d80941d20796cdee8d7\/href\">https:\/\/medium.com\/media\/e78f20d4b9370d80941d20796cdee8d7\/href<\/a><\/p>\n<h3>Deployment Notes<\/h3>\n<p>A few things worth knowing for operational use:<\/p>\n<p><strong>Run as a regular user.<\/strong> The service does not need root. The installer creates the systemd unit under your own user\u00a0account.<\/p>\n<p><strong>One Gunicorn worker.<\/strong> This is intentional. Telethon\u2019s session file is a SQLite database and does not handle concurrent writes from multiple processes. Two workers will cause database is locked errors on the session file. One worker, no\u00a0problem.<\/p>\n<p><strong>Session file security.<\/strong> data\/channel_monitor.session grants access to your Telegram account. It is in\u00a0.gitignore and will never be committed, but treat it like a password. If you are running this on a shared or internet-facing machine, consider the same OPSEC guidance from the original post\u200a\u2014\u200aa dedicated SIM or a service like TextVerified keeps your personal number out of the\u00a0picture.<\/p>\n<p><strong>Hostname access.<\/strong> The service binds to 0.0.0.0 so you can reach it by IP, hostname, or localhost. If you are on a local network and want to hit it from another machine, just use the hostname: <a href=\"http:\/\/your-machine\/\">http:\/\/your-machine:5000.<\/a><\/p>\n<h3>What Is\u00a0Next<\/h3>\n<p>The standalone version is v1. A few things are still missing that I want to\u00a0add:<\/p>\n<p><strong>Cancel a running scan from the UI.<\/strong> Right now you can only let it finish or restart the service. A stop button is straightforward to add and it is on the\u00a0list.<\/p>\n<p><strong>Progress indication.<\/strong> The log tells you everything but there is no progress bar showing X of N messages complete. For channels where you set limit to 0 and fetch everything, that\u00a0matters.<\/p>\n<p><strong>Multi-channel batch scanning.<\/strong> The CLI already supports a channels file with one channel per line. The UI should too\u200a\u2014\u200apaste in a list, kick off scans sequentially, get one ZIP per\u00a0channel.<\/p>\n<p><strong>IOC extraction on translated output.<\/strong> This was in the roadmap from the original post and it is still there. The translated messages.json is a natural input for entity extraction\u200a\u2014\u200alocations, unit names, coordinates, dates. Connecting that to the keyword scanner in the main platform is the logical next\u00a0step.<\/p>\n<p>The repo is at <a href=\"https:\/\/github.com\/osintph\/channel-monitor-ui\"><strong>https:\/\/github.com\/osintph\/channel-monitor-ui<\/strong><\/a> and it is open source. The install takes five minutes on any Debian-based system. If you run into issues or have feature requests, open an issue or reach out directly.<\/p>\n<p><a href=\"https:\/\/github.com\/osintph\/channel-monitor-ui\">GitHub &#8211; osintph\/channel-monitor-ui<\/a><\/p>\n<p>Session Messenger: 059db238ab37c3d92615c5cc24b694da29c598cc13e27886053722404118e14271<\/p>\n<p><em>All monitoring was conducted on publicly accessible Telegram channels for research and OSINT purposes.<\/em><\/p>\n<p>As usual:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.osintph.info\/\">OSINT PH &#8211; Digital Forensics &amp; Cybersecurity Consulting<\/a><\/li>\n<li><a href=\"https:\/\/www.cybernewsph.com\/\">CyberNewsPH &#8211; Philippine Cybersecurity &amp; Data Privacy News<\/a><\/li>\n<li><a href=\"https:\/\/buymeacoffee.com\/sigmundg?source=post_page-----bc1f6c96f3f6---------------------------------------\">Sigmund Brandstaetter<\/a><\/li>\n<\/ul>\n<p><img data-opt-id=574357117  decoding=\"async\" src=\"https:\/\/medium.com\/_\/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=6f65cb23b75a\" width=\"1\" height=\"1\" alt=\"\" \/><\/p>\n<hr \/>\n<p><a href=\"https:\/\/osintteam.blog\/channel-monitor-gets-a-standalone-web-ui-6f65cb23b75a\">Channel Monitor Gets a Standalone Web UI<\/a> was originally published in <a href=\"https:\/\/osintteam.blog\/\">OSINT Team<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>","protected":false},"excerpt":{"rendered":"<p>If you have been following this series, you know the history. The first version was a command-line Python script\u200a\u2014\u200ayou ran it, it scraped a Telegram channel, translated everything, downloaded the media, and dropped a self-contained HTML report into an output folder. Useful, but you had to be comfortable with a terminal and you had to &#8230; <a title=\"Channel Monitor Gets a Standalone Web UI\" class=\"read-more\" href=\"https:\/\/quantusintel.group\/osint\/blog\/2026\/03\/24\/channel-monitor-gets-a-standalone-web-ui\/\" aria-label=\"Read more about Channel Monitor Gets a Standalone Web UI\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":431,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-430","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/posts\/430","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/comments?post=430"}],"version-history":[{"count":0,"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/posts\/430\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/media\/431"}],"wp:attachment":[{"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/media?parent=430"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/categories?post=430"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/quantusintel.group\/osint\/wp-json\/wp\/v2\/tags?post=430"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}