The headline of this release is species name localization for every model: detections from Perch v2 and BattyBirdNET used to show as raw scientific names, and now the majority of species resolve to proper common names in your configured language, thanks to an embedded OpenFauna dataset that is now the authoritative naming source across the dashboard, analytics, search, and species settings. This release also adds an opt-in Private Mode that locks the whole UI and API behind login, three new contributor features (a New & Returning Species widget, source badges on detections, and sortable species tables), and an important security fix that stops source-IP spoofing through forwarded headers on directly-exposed instances.
New Features
Localized Common Names for Every Model
Species detected by secondary models such as Perch v2 and BattyBirdNET previously displayed as raw scientific names, because those models only ship scientific-only labels. BirdNET-Go now resolves names through a vendored, embedded OpenFauna dataset (40+ locales), so the large majority of species, birds and bats alike, show proper common names in your configured species language across the dashboard, analytics charts and tables, detection detail, search, the species settings pickers, and CSV exports. Force-include and exclude lists, as well as search, now also accept localized common names for these scientific-only species (so a Finnish "mopsilepakko" resolves to Barbastella barbastellus). This is a display and search overlay only: MQTT, BirdWeather, notifications, the public API, RSS, and the stored database names continue to use the server-configured locale (#3404, #3406, #3407, #3450, #3452, #3454, #3460, #3461, #3464, #3468, #3469, #3504, #3506).
Two notes for upgraders: OpenFauna is now the naming authority, so for the default en-uk locale a handful of species names shift from IOC British forms to eBird/American forms (for example "Common Magpie" becomes "Eurasian Magpie"), and a search for the old name no longer matches. Separately, per-visitor browser-language localization (showing names in each visitor's own UI language) is wired in but ships off by default; it stays dormant behind a kill switch pending a dedicated per-visitor species-language preference that is independent of the UI chrome language (#3463, #3474).
Private Mode
A new Security.PrivateMode toggle (default off) locks the entire dashboard and v2 API behind authentication, for operators who do not want any read-only UI or API reachable from the internet. With it on, every endpoint except the small login-bootstrap allow-list requires authentication, and the SPA shows a full-screen login. It is strictly additive: with the toggle off, the existing guest-friendly behavior is unchanged, and the setting hot-reloads without a restart (#3122 by @TeTeHacko).
Re-Alert on Rising Confidence
Detection alert rules can now notify again when a species crosses a higher configured confidence step, scoped to the species and novelty episode, instead of being suppressed for the whole cooldown window. A rare bird that starts as a low-confidence detection and grows more convincing will now alert again at the higher step (#3288 by @keithkml).
New & Returning Species Widget
An optional dashboard widget surfaces species carrying a novelty indicator (new lifetime, new this year, or new this season) for the selected day, with a confidence pill, detection count, and a "last seen N days ago" gap for returning species. It renders nothing on quiet days and adds no extra network requests (#3376 by @alexbelgium).
Source Badges on Detections
Detections now show which microphone or RTSP source heard each bird, across detection cards, tables, the detail view, analytics, and the currently-hearing card. Search gains a source filter to match (#3101 by @TeTeHacko).
Sortable Species Tables
The analytics Species page columns are now click-to-sort, with the sort order persisted across refreshes and kept in sync with the filter dropdown (#3325 by @alexbelgium). The species settings Custom tab was also redesigned from a flat, header-less list into a sortable, searchable table matching the sibling Active tab (#3508).
Precipitation in Weather Data
The yr.no, OpenWeather, and Wunderground providers already collected a precipitation amount and a high-level condition category, but both were dropped before reaching the database. They are now persisted and exposed through the weather API and the detection-detail weather panel (#3495).
Detection Drops on System Health
Detections dropped because the classifier results queue was full were previously only visible in logs. The System Health page now surfaces these drops with windowed counts and trend indicators, so users on constrained hardware can see when they are losing detections, and how many (#3497).
Native FLAC Encoder (Preview, opt-in via BIRDNET_FLAC_ENCODER=native)
This release adds an experimental pure-Go FLAC encoder and EBU R128 audio-normalization path that removes the FFmpeg dependency for detection-clip exports and BirdWeather soundscape uploads. With the BIRDNET_FLAC_ENCODER=native environment variable set, FLAC clips and BirdWeather uploads are encoded in-process, which avoids the FFmpeg subprocess failures (encode timeouts, broken pipes, missing or misconfigured ffmpeg) that recur on resource-constrained and container deployments.
This is off by default and experimental. With the variable unset, the existing FFmpeg path runs unchanged and is byte-for-byte identical to before. The native path is gated so it can earn confidence in the field before becoming the default; there is no settings or UI for it yet (#3483, #3502, #3512).
Security
- Forwarded client-IP headers now require a trusted proxy -
CF-Connecting-IP,X-Forwarded-For, andX-Real-IPwere honored from any peer, so a client on a directly-exposed instance could forge its source IP, which feeds login rate limiting, subnet-bypass auth, and request logs. These headers are now trusted only from loopback/private peers by default, plus a new hot-reloadableSecurity.TrustedProxiesCIDR list (the reserved value"cloudflare"expands to Cloudflare's edge ranges). Upgrade note: a reverse proxy that connects from a public IP must be added toTrustedProxiesfor forwarded headers to be honored again (#3393). - Open-redirect hardening on login - post-login redirect targets are now validated and base-path-aware, so a crafted redirect cannot send users off-site after authentication (#3360).
- Weather provider logs no longer leak secrets - API keys and request coordinates are now scrubbed from provider error logs and wrapped errors, and endpoint schemes are validated (#3448, #3451, #3456).
Bug Fixes
Audio & Streaming
- Per-stream channel selector showed blank after reload - an unset channel mode came back as an empty string that the form's default did not catch, so the dropdown showed "Select..." after every reload. The control now adapts to the source (selector for multi-channel, a note for mono), surfaces the detected stream format, and no longer triggers a needless stream restart on an empty-vs-explicit downmix transition (#3357).
- iOS/iPad Safari played clips silently - when the shared AudioContext was still suspended, the players routed audio into the suspended graph, which on iOS permanently silences the element. Clips now play through the native output while suspended and attach the Web Audio graph only once the context is running (#3511).
- Stream test gave a generic error for audio-less streams - testing a URL with no audio stream now reports that specifically instead of a generic connection failure (#3429 by @kv1sidisi).
- Audio exports now use dual-pass loudness normalization for more consistent clip levels (#3367).
Authentication
- Basic auth and OAuth settings now hot-reload - changing them in Security settings takes effect immediately without a server restart (#3379).
- Post-login redirect preserves the query string - you now land back on the exact page you requested, including its query parameters (#3359).
- OIDC reliability and UX - per-issuer retry lifecycle for OIDC, OAuth login flow logged to the security module, and clearer allowed-users guidance in the settings UI (#3390, #3384).
Dashboard & Analytics
- Mobile dashboard now uses a single-column layout instead of a cramped multi-column grid (#3274 by @keithkml).
- Detection search now matches common names, not just scientific names (#3385).
- Analytics timezone handling - charts and SQL now bucket dates, years, and hours by the configured timezone instead of UTC, and analytics queries apply a consistent timeout and return 408 on deadline (#3475, #3476, #3467).
- Assorted UI fixes - the species image popup aligns to the row top in the above position, a permanent horizontal scrollbar was removed from the daily stats grid, and several dropdown, fetch-race, search-filter, and audio-playback edge cases were fixed (#3498, #3505, #3494).
Weather
- Weather polling recovers after a settings change - the polling lifecycle, hot-reload recovery, and backoff state machine were hardened so weather updates resume correctly after settings are changed at runtime (#3453).
Infrastructure & Platform
- Rootless container startup - the container no longer tries to link system timezone files (which fails under a rootless or arbitrary user); it reads the
TZenv var directly and falls back to UTC with clear guidance when the timezone cannot be resolved (#3369 by @bo0tzz). - systemd host timezone - the systemd service generator now detects the host timezone via
timedatectland/etc/localtime(#3351).