Live cam / For researchers / Open data
Open trout behavior data
A continuous, public record of wild trout in a cold mountain stream: when fish are present, what they're doing, which individuals come back, and how the water looks, minute by minute. Free to use under CC BY 4.0.
Days of data
5
Since 2026-11-02
Sightings (last 30 days)
1,575
2,134 fish-minutes on camera
Behaviors logged
2,812
348 feeding, 1826 darts, 638 holds
Downloads
- sightings.csv: every sighting in the last 30 days, with duration, behavior counts and fish ID
- hourly.csv: behavior by hour of day, normalized by time on camera
- fish.csv: individual fish identified by spot pattern (profiles)
- Daily minute data and event logs, Mountain Time dates. Days older than 30 come from the archive:
| 2026-11-05 | minutes | events |
| 2026-11-04 | minutes | events |
| 2026-11-03 | minutes | events |
| 2026-11-02 | minutes | events |
| 2026-11-01 | minutes | events |
| 2026-10-31 | minutes | events |
| 2026-10-30 | minutes | events |
| 2026-10-29 | minutes | events |
| 2026-10-28 | minutes | events |
| 2026-10-27 | minutes | events |
| 2026-10-26 | minutes | events |
| 2026-10-25 | minutes | events |
| 2026-10-24 | minutes | events |
| 2026-10-23 | minutes | events |
Live and programmatic access: feeding summary JSON, OpenAPI, and an MCP server for AI agents.
Data dictionary
| File | Field | Meaning |
|---|---|---|
| minutes CSV | time_mt | Minute timestamp, Mountain Time |
| minutes CSV | fish_now / fish_max | Fish detected in frame (latest / most in the minute) |
| minutes CSV | fish_seconds | Seconds in the minute with at least one fish in view |
| minutes CSV | drift | Count of small drifting particles detected (relative) |
| minutes CSV | clarity_pct | Bottom-detail sharpness vs. a reference (0-100); method being upgraded, see limitations |
| minutes CSV | flow_pct | Surface/drift motion vs. normal for this camera (100 = normal) |
| minutes CSV | light_pct | Scene brightness (0-100) |
| minutes CSV | visibility | How far bottom detail survives: far, mid, near or bottom (new near/mid/far method; blank before it was switched on) |
| events CSV | kind | arrive, leave, hold, dart, grub (feeding move), company (2+ fish), shadow, muddy, clearing |
| sightings.csv | holds / darts / feeding_moves / company | Behavior counts within one continuous sighting |
| sightings.csv | fish, id_confidence | Named fish matched by spot pattern, and match confidence |
| fish.csv | spot_matches | Times the fish's spot pattern was matched |
| hourly.csv | feeding_per_10_fish_min | Feeding moves per 10 minutes of fish time in view |
Methods
A DWE exploreHD 1080p underwater camera sits on the bed of a small, cold mountain stream below a waterfall, looking along the bottom. A Raspberry Pi beside the stream analyzes the video in real time and streams it live from about 30 minutes before sunrise to 30 minutes after sunset.
- Detection and behavior. Moving fish are detected by image analysis. Each continuous sighting is labeled with movement types: holding station, darting, feeding moves (short strikes or rises), and company (two or more fish).
- Individuals. Fish are re-identified by the pattern of black spots on their flanks. A face (one side of one fish) earns a name only after matching on 3 visits at least 10 minutes apart with 40+ spots aligned, and after its matches span at least an hour. Each side is matched separately.
- Water. Clarity is estimated from how much fine bottom detail is visible; flow from motion in the scene; rain from the National Weather Service.
- Fish-minutes. Rates are normalized by total time fish were in view, so hours with more fish don't look more active just because of numbers.
Limitations
- Behavior labels are unvalidated. In hand review so far, 1 of 12 automatically flagged feeding clips showed a real feeding event or rise. Use counts for relative patterns, not absolute rates.
- Re-identification makes mistakes. A rock was once given a fish name and was removed by hand. Sightings without a confident match are left unnamed.
- Clarity is relative. The current number compares bottom sharpness with recent conditions, so it isn't comparable across days or camera positions. It is being replaced with a fixed near/mid/far visibility measure.
- No water temperature yet. The temperature in the Pi's health data is the computer's own, not the stream's.
- The camera was repositioned on 2026-11-03, so compare data before and after that date with care.
- One camera and one pool, with a narrow field of view. Fish counts are sightings, not population size.
How to cite
OnlyFins underwater trout cam, https://onlyfins.stream. CC BY 4.0 (credit OnlyFins with a link).
@misc{onlyfins_trout_cam,
title = {OnlyFins: live underwater trout camera, behavior and stream-condition data},
author = {{OnlyFins}},
year = {2026},
howpublished = {\url{https://onlyfins.stream/trout/research}},
note = {Accessed 2026-11-05. CC BY 4.0}
}
Based on 5 days of camera data (2026-11-01 to 2026-11-05). Behaviors are labeled automatically by motion analysis and haven't been validated against hand counts, so treat these as patterns to watch, not findings. One camera, one pool.