A Python script that checks your Groups.io mailing lists and produces a daily digest report — an HTML file that opens in your browser with clickable topic links, and a plain-text copy for archiving or forwarding.
No external libraries required. Runs on Windows, macOS, and Linux.
Each time you run it, the script:
- Connects to the Groups.io API using your API key
- Fetches recent topics from every group you've configured
- Filters to activity within your chosen time window (default: 7 days)
- Produces a ranked HTML report (most active groups first) with clickable thread titles
- Saves a plain-text copy
- Opens the HTML report in your default browser
Groups with no recent activity are collected at the bottom. Groups where the owner has disabled API access are noted separately rather than shown as errors.
- Python 3.8 or later
- A Groups.io account with an API key
- Membership in the groups you want to monitor
No pip install needed — the script uses only Python's standard library.
-
Install Python from the Microsoft Store — search for Python 3.13. This installs the native ARM64 build on ARM devices automatically.
-
Download
groupsio_digest.pyand save it somewhere convenient, such as your Desktop or Documents folder.
Python 3 is usually already installed. Download groupsio_digest.py and you're ready.
- Log into groups.io and go to Settings → API Keys (direct link: https://groups.io/settings/apikeys)
- Click + Create API Key, give it a name (e.g. Groups Digest), and click Create
- Copy the key immediately — Groups.io only shows the full key value once
- Paste it into the script (see Configuration below)
The API key authenticates as you, so it can only access groups you're already a member of.
Open groupsio_digest.py in any text editor (Notepad, VSCode, etc.) and edit the values near the top of the file.
API_KEY = "paste-your-key-here"Recommended: keep your key out of the file entirely. If you ever fork this repo or push your own changes back to GitHub, an API key pasted directly into the script can get committed by accident. Two supported alternatives, described in full in Keeping secrets out of GitHub below:
- Copy
config.py.exampletoconfig.pyand put your key there — it's gitignored, so it never gets committed. - Set the
GROUPSIO_API_KEYenvironment variable — handy for cron jobs or CI (e.g. GitHub Actions secrets).
LOOKBACK_DAYS = 7 # Change to any number of daysOUTPUT_DIR = Path.home() / "Documents" / "GroupsIO_Digest"Reports are saved here as timestamped files, e.g. digest_2026-06-10_0830.html.
The GROUPS list near the top of the script controls which groups are monitored. Each entry is a dictionary with three fields:
{"name": "Display Name", "group": "slug", "domain": "groups.io"}- name — how it appears in the report (your choice)
- group — the slug from the group's URL
- domain — usually
groups.io; use the subdomain for groups with custom domains
For a group at https://groups.io/g/linuxham:
{"name": "LinuxHam", "group": "linuxham", "domain": "groups.io"},Groups.io supports parent groups with subgroups underneath them. These have their own subdomain (e.g. ardc.groups.io) but the API uses a parent+subgroup slug format:
For a subgroup at https://ardc.groups.io/g/44net:
{"name": "ARDC: 44Net", "group": "ardc+44net", "domain": "groups.io"},The pattern is always parentname+subgroupslug, all lowercase, pointed at plain groups.io as the domain.
More examples:
# https://ardc.groups.io/g/44Net-connect
{"name": "ARDC: 44Net Connect", "group": "ardc+44Net-connect", "domain": "groups.io"},
# https://dmr.groups.io/g/PNW
{"name": "PNW DMR", "group": "dmr+PNW", "domain": "groups.io"},Some group owners disable API access to their archive. There's nothing you can do about this from your end — it's a setting they control. Mark these groups with "restricted": True to skip them cleanly:
{"name": "Example Group", "group": "example", "domain": "example.groups.io", "restricted": True},They'll appear in a neutral API access restricted section rather than the error list.
Some groups allow API access but have closed archives — meaning you can fetch activity data as a member, but non-members can't follow topic links or read thread subjects. If you publish your digest publicly (on a blog or website), mark these groups with "members_only": True:
{"name": "Example Group", "group": "example", "domain": "groups.io", "members_only": True},The script will still fetch and count messages for these groups, but will omit topic titles and links from the report. They appear in a separate "Members Only" section showing only the group name and message count.
This is different from "restricted": True, which skips the group entirely because the owner has disabled API access.
You don't need to paste your real API key (or your private group list) directly into groupsio_digest_public.py. Two supported ways to externalize them, checked in this order — an environment variable wins over config.py, which wins over the placeholders in the script:
- Copy
config.py.exampletoconfig.py, in the same folder as the script. - Open
config.pyand paste your real API key in place of the placeholder. - Run the script as usual — it picks up
config.pyautomatically.
config.py is listed in .gitignore, so git add / git commit will never pick it up, even if you fork this repo or push your own changes. You can also move your GROUPS list, LOOKBACK_DAYS, or OUTPUT_DIR into config.py the same way — see the comments in config.py.example for the format. This is the simplest option if you're running the script locally on Windows/macOS/Linux via Task Scheduler or cron.
Set GROUPSIO_API_KEY (and, optionally, GROUPSIO_OUTPUT_DIR) wherever the script runs — your shell profile, a cron job's environment, or a CI secret. This is the more natural fit for automated/scheduled setups, especially GitHub Actions: see .github/workflows/digest.yml.example for a ready-to-adapt scheduled workflow that reads your key from a GitHub repository secret, runs the digest on a cron schedule, and uploads the generated report. Rename it (drop .example) after adding a GROUPSIO_API_KEY secret under your repo's Settings → Secrets and variables → Actions.
When the script detects it's running inside GitHub Actions (or you set GROUPSIO_DIGEST_HEADLESS=1 yourself for a cron job), it automatically skips opening a browser window and waiting for a keypress at the end, so it won't hang in a non-interactive environment.
Windows: Right-click groupsio_digest.py → Open with → Python
Command line (all platforms):
python groupsio_digest.py
The script prints progress to the console as it fetches each group, then opens the HTML report in your browser when done.
- Press Win + S, search for Task Scheduler, open it
- Click Create Basic Task on the right
- Name it Groups.io Digest, click Next
- Choose Daily, set your preferred time (e.g. 7:00 AM)
- Choose Start a program
- Program/script:
python - Add arguments:
"C:\Users\YourName\Desktop\groupsio_digest.py"(adjust path to where you saved the script) - Click Finish
0 7 * * * /usr/bin/python3 /home/yourname/groupsio_digest.py
Groups.io API keys use HTTP Bearer token authentication. The script sends your key as an Authorization: Bearer header on every request. The key is stored only in the script file on your local machine — it is never sent anywhere except directly to the groups.io API.
If you belong to groups under different Groups.io accounts (different email addresses), you can add a second API key for the other account and assign it per-group. See the comments in the script for details.
unauthorized_error on startup
Your API key isn't being accepted. Double-check it matches exactly what's shown at groups.io/settings/apikeys — no extra spaces or missing characters.
group_not_found for a group
The slug in your GROUPS list doesn't match what Groups.io expects. Visit the group in your browser, copy the URL, and check the slug. For subgroups, make sure you're using the parent+subgroup format described above.
inadequate_permissions for a group
The group owner has restricted API access. Add "restricted": True to that group's entry to suppress the error.
Script window closes immediately on Windows Run it from the command prompt instead so you can read any error messages:
python "%USERPROFILE%\Desktop\groupsio_digest.py"
All topics show message count of (1)
You may have an older version of the script. The topic message count field in the Groups.io API is num_messages, not message_count. Make sure you're running the current version.
Opens automatically in your browser. Groups are sorted by total message count (most active first). Each topic title is a clickable link that takes you directly to that thread on Groups.io.
Saved alongside the HTML file. Same information in plain text — useful for forwarding by email or reading in a terminal.
Both files are named with a timestamp: digest_YYYY-MM-DD_HHMM.html / .txt
- The Groups.io API returns up to 100 topics per group per request. For very high-volume groups this may not capture everything within the lookback window, though it's sufficient for typical amateur radio mailing lists.
- The script shows up to 5 topics per group in the report. Edit the
[:5]slice inbuild_html_report()andbuild_text_report()to show more. - Groups where the owner has disabled API access cannot be monitored regardless of your membership status.
Written for amateur radio operators monitoring Groups.io mailing lists, but works for any Groups.io group.