CSS swim training pace calculator
With a CSS of 1:30 per 100 m, offsets of minus 5, zero and plus 10 seconds give paces of 1:25, 1:30 and 1:40. Enter your CSS and the offsets you train with to get every pace and hold time at once. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Css s per 100
- 90
- Offsets s
- -5, -2, 0, 2, 5, 10
- Distance m
- 100
- Css per 100
- 1:30
- Offset count
- 6
Critical Swim Speed (CSS) is a practical threshold pace that coaches and age-group swimmers use to set aerobic and threshold interval work without a lab VO2 test. Once you know CSS in seconds per one hundred metres, training sets are built by adding or subtracting a few seconds: faster offsets for race-pace sharpness, CSS itself for threshold repeats, and slower offsets for aerobic volume and recovery-oriented pull. This CSS swim training pace calculator turns a single CSS value and a list of second offsets into a full table of paces per one hundred metres plus hold times for any interval distance you choose. The math is pure and offline: pace equals CSS plus offset, and hold time scales with distance over one hundred metres.
What Critical Swim Speed means for interval sets
Critical Swim Speed is usually estimated from two maximal efforts of different distances, classically four hundred and two hundred metres, by taking the slope of distance versus time. That slope is a velocity; coaches almost always convert it back into a pace clock string such as one minute thirty per hundred metres so athletes can hold it on a pace clock. CSS sits near aerobic threshold for many trained freestylers, so long sets at CSS develop the ability to clear lactate while still swimming with good stroke economy.
Race-specific work sits a few seconds faster than CSS per hundred; extensive aerobic sets sit several seconds slower so the swimmer can complete high volume with controlled heart rate. Because the ladder is defined in seconds per hundred rather than heart-rate zones alone, the same prescription travels across twenty-five metre and fifty-metre pools: multiply the per-hundred pace by the fraction of a hundred that the repeat is.
This capability takes CSS and a list of offsets and materialises that ladder so a coach can publish “CSS minus three, CSS flat, CSS plus five” without recalculating every hold time by hand for two hundred metre repeats or fifty metre sprints. It does not estimate CSS from test times; feed a CSS you already measured or trust, then generate the training table around it.
Who uses a CSS pace table and why
Club coaches building weekly cycles need a deterministic table whenever CSS is retested after a taper or base block; regenerating offsets by spreadsheet invites transcription errors on the whiteboard. Content sites ranking for CSS swim training pace calculator benefit from a free browser tool whose answers match the paid automation path byte for byte. Strength-and-conditioning staff working with multi-sport athletes can convert a shared CSS into mixed-pace sets (threshold plus recovery) that still respect the same second-offset language used on pool decks.
What you can do with it
Club set design from a known CSS
Enter the squad CSS and offsets such as −3, 0, +5, +10 to print pace-per-100 and hold times for the written set on the whiteboard.
Training app interval builder
When an athlete updates CSS after a test set, regenerate training zones as second offsets and show hold times for 50 m, 100 m, and 200 m repeats.
FAQ
How do I compute CSS training paces?
Pace = CSS + offset; hold = pace × (distance/100).
What do positive and negative offsets mean?
Negative offsets are faster than CSS (harder); positive offsets are slower (easier); zero is CSS itself. Each CSS + offset must remain strictly positive.
Does this calculator estimate Critical Swim Speed from test swims?
No. Provide a CSS you already measured (for example from 400 m and 200 m efforts). This tool only builds the offset ladder and hold times around that CSS.
How do I get hold times for 200 m or 50 m repeats?
Set the repeat distance and each hold time is the pace per 100 m scaled to it. A 200 m repeat takes twice the per-hundred pace and a 50 m sprint half of it, so you never redo the sums on the whiteboard.
Does the table work in both 25 m and 50 m pools?
Yes. Paces are set in seconds per 100 m rather than by pool length, so the same prescription carries over to either pool; only the repeat distance you choose changes the hold time.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/health/css-training-paces \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"css_s_per_100":90,"offsets_s":[-5,-2,0,2,5,10]}'const res = await fetch("https://api.kit.forhosting.com/health/css-training-paces", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"css_s_per_100": 90,
"offsets_s": [
-5,
-2,
0,
2,
5,
10
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/health/css-training-paces",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"css_s_per_100": 90,
"offsets_s": [
-5,
-2,
0,
2,
5,
10
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/health/css-training-paces", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"css_s_per_100":90,"offsets_s":[-5,-2,0,2,5,10]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"css_s_per_100":90,"offsets_s":[-5,-2,0,2,5,10]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/health/css-training-paces", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"css_s_per_100": 90,
"offsets_s": [
-5,
-2,
0,
2,
5,
10
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "health.css_training_paces",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Invalid or non-positive inputs fail cleanly with invalid_input so coaching tools and training apps never invent a negative pace.
Input contract, formulas, and error behaviour
Missing CSS, non-finite numbers, empty offset lists, and non-positive distance also fail without billing. Numeric fields are rounded to six decimal places for stable automation; display strings round fractional seconds to the nearest whole second in M:SS or H:MM:SS form. Example: CSS ninety with offsets negative five, zero, and ten over one hundred metres yields eighty-five, ninety, and one hundred seconds per hundred—clocked as one twenty-five, one thirty, and one forty. Send css_s_per_100 as a finite positive number of seconds per one hundred metres—for example ninety for a one minute thirty CSS. Send offsets_s as a non-empty array of finite second offsets: negative values are faster than CSS, zero is CSS itself, and positive values are slower. Optionally send distance_m (default one hundred) as the interval repeat distance in metres so each row includes both pace per hundred and the hold time for that repeat. The identities are pace_s_per_100 equals css_s_per_100 plus offset_s, and hold_s equals pace_s_per_100 times distance_m divided by one hundred. Each resulting pace must stay strictly positive; an offset that drives CSS plus offset to zero or below is rejected as invalid_input. On success the response echoes CSS and distance, reports offset_count, and returns paces as an ordered array of objects with offset_s, pace_s_per_100, a clock string pace_per_100, hold_s, and a clock string hold.
Where a CSS training-pace API earns its keep
Training apps that store CSS per athlete can call this endpoint when the user designs an interval set and show hold times for fifty, one hundred, or two hundred metre repeats without shipping swimming math into every client.
Integration use cases
Coaching SaaS and LMS checks
Automate CSS-based prescriptions in lesson plans with a deterministic API so every client sees the same pace table for the same inputs.
Technical questions
What inputs are rejected?
Missing or non-positive CSS, empty or non-array offsets, non-finite numbers, non-positive distance_m, and any offset that makes pace zero or negative. Those fail with invalid_input and are not billed.
What does the CSS swim training pace calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.