The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
rCoros gives you tidy access to your COROS Training Hub data from R. Every function returns a tibble, so you can pipe results straight into dplyr and ggplot2.
Store your credentials in ~/.Renviron so they are never
hard-coded in a script:
COROS_EMAIL=you@example.com
COROS_PASSWORD=secret
Then restart R and authenticate:
library(rCoros)
auth <- coros_login()
auth
#> <coros_auth>
#> region: us
#> user_id: 123456789
#> logged in: 2026-06-07 08:00:00Pass region = "eu" if your account was created in
Europe. The auth object is just a lightweight list — create
it once per session and pass it to every subsequent call.
coros_activities() returns one row per activity. By
default it fetches the last 30 days and auto-paginates until all
matching activities are returned:
library(dplyr)
acts <- coros_activities(auth)
acts
#> # A tibble: 47 × 16
#> activity_id name sport_type sport_name date start_time
#> <chr> <chr> <int> <chr> <date> <dttm>
#> 1 4780… Morning Trail R… 102 Trail Run… 2026-06-06 2026-06-06 06:12:00
#> 2 4779… Easy Run 100 Running 2026-06-04 2026-06-04 07:00:00
#> …Filter to runs only, then look at distance and training load over time:
runs <- acts |>
filter(sport_type %in% c(100L, 102L)) |>
arrange(date)
library(ggplot2)
ggplot(runs, aes(date, distance_km)) +
geom_col(fill = "#3A7BD5") +
labs(title = "Weekly volume", x = NULL, y = "Distance (km)")Drill into a single activity to get lap splits and heart-rate zones:
detail <- coros_activity_detail(
auth,
activity_id = acts$activity_id[[1]],
sport_type = acts$sport_type[[1]]
)
# One-row summary
detail$summary |> glimpse()
# Lap splits
detail$laps
# Time in HR zones
ggplot(detail$hr_zones, aes(factor(zone), minutes, fill = factor(zone))) +
geom_col(show.legend = FALSE) +
scale_fill_brewer(palette = "RdYlGn", direction = -1) +
labs(title = "Time in HR zones", x = "Zone", y = "Minutes")coros_daily_metrics() pulls per-day HRV, resting heart
rate, VO2max, training load, and more for up to 90 days at a time:
metrics <- coros_daily_metrics(auth, start_day = "20260101", end_day = "20260607")
# HRV trend with baseline
ggplot(metrics, aes(date)) +
geom_ribbon(aes(ymin = hrv_baseline - 5, ymax = hrv_baseline + 5),
fill = "steelblue", alpha = 0.2) +
geom_line(aes(y = hrv_baseline), colour = "steelblue", linewidth = 0.8) +
geom_point(aes(y = hrv), size = 1.5) +
labs(title = "Overnight HRV vs. baseline", x = NULL, y = "HRV (ms)")For a quick view of just the last 7 days, coros_hrv()
hits a lighter dashboard endpoint:
Training load and its acute:chronic ratio are in
coros_daily_metrics(). A ratio above ~1.5 is a useful proxy
for injury risk:
metrics |>
filter(!is.na(load_ratio)) |>
ggplot(aes(date, load_ratio)) +
geom_hline(yintercept = c(0.8, 1.3), linetype = "dashed", colour = "grey60") +
geom_line(colour = "#E06C2C", linewidth = 1) +
annotate("text", x = min(metrics$date), y = 1.35,
label = "Caution zone", hjust = 0, size = 3, colour = "grey40") +
labs(title = "Acute:chronic training load ratio",
x = NULL, y = "Load ratio")coros_workouts() returns your saved workout library as
two linked tibbles — the workout header and its individual steps:
coros_schedule() shows what’s planned for the next two
weeks (or any window you specify):
A common pattern is to join activities back to daily metrics to explore how recovery scores relate to performance:
combined <- runs |>
left_join(
metrics |> select(date, hrv, hrv_baseline, rhr, load_ratio),
by = "date"
)
ggplot(combined, aes(hrv, avg_hr, colour = load_ratio)) +
geom_point(size = 2.5) +
geom_smooth(method = "lm", se = FALSE, colour = "grey40") +
scale_colour_viridis_c(name = "Load ratio") +
labs(
title = "HRV vs. average run HR",
x = "Overnight HRV (ms)",
y = "Average HR (bpm)"
)These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.