Hardness conversion
A city report of 100 ppm hardness is 5.8479532164 grains per gallon on a US softener chart. Move one reading between ppm, mg/L, grains per gallon, German, French and Clark degrees, mmol/L and meq/L through a single calcium carbonate bridge. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Value
- 100
- From
- Ppm
- To
- Gpg
- Result
- 5.8479532164
- From label
- parts per million
- To label
- grains per gallon
- Value ppm
- 100
Hardness conversion rewrites a numeric water-hardness reading from one reporting unit into another without changing the underlying calcium-carbonate equivalent. This calculator accepts parts per million, milligrams per liter, grains per US gallon, German degrees, French degrees, English Clark degrees, millimoles per liter, and milliequivalents per liter, then returns the converted magnitude with canonical identifiers and a published factor table. One part per million equals one milligram per liter, one grain per gallon equals 17.1 parts per million, one German degree equals 17.8, one French degree equals ten, and one Clark degree equals 14.3, so every path bridges through a single ppm intermediate. Arithmetic is finite, deterministic, and free of network calls. Typical checks include one hundred parts per million to grains per gallon and ten German degrees into French degrees.
Where hardness conversion fits in plumbing, labs, and software
Municipal reports, European softener manuals, and North American appliance guides often mix parts per million, milligrams per liter, grains per gallon, and several degree systems, so a single deterministic converter prevents hand-calculator drift when a plumber, homeowner, student, or developer compares readings across devices and papers.
Softener installers convert a municipal ppm report into grains per gallon for capacity tables; export teams map German degree setpoints into French degrees or milligrams per liter for dual-system datasheets; laboratory notebooks rewrite millimoles per liter into milliequivalents per liter when two methods share a sample. Teachers assign homework that needs a fast, offline check of the 17.1, 17.8, 10, and 14.3 factors without trusting opaque apps that silently change precision.
Developers call the same contract from scripts to seed deterministic test vectors for water-treatment user interfaces, to normalize user-entered hardness before charting demos, or to satisfy programming-challenge statements that demand exact published factors rather than a hand-waved estimate. Product tools use the rewrite when a learner types one hundred ppm and the interface must show grains per gallon and German degrees side by side.
Pair it with general concentration converters when you need molarity for other solutes, and remember this tool does not classify soft versus hard water or recommend treatment equipment.
What you can do with it
Softener capacity tables from a municipal ppm report
Convert a city hardness certificate in parts per million or milligrams per liter into grains per gallon so North American softener sizing charts, install notes, and appliance manuals share one unit.
Dual-system export datasheets across degree scales
Map German degrees into French degrees, Clark degrees, or milligrams per liter when a European product sheet must quote more than one hardness scale without hand-calculator drift.
FAQ
How many parts per million sit in one grain per gallon or one German degree?
Every conversion bridges through parts per million as CaCO3 equivalent.
What happens when the target unit is unsupported?
Unknown strings are never silently remapped to a nearby scale.
Does hardness conversion tell me whether my water is soft or hard?
No. It only rewrites hardness units among ppm, mg/L, grains per gallon, degree scales, mmol/L, and meq/L. It does not attach category labels or recommend treatment equipment.
How do I convert German degrees to French degrees?
Multiply the German degrees by 17.8 to get ppm, then divide by 10, since one French degree is 10 ppm. Ten German degrees therefore equal 17.8 French degrees.
How many ppm are in one mmol/L or one meq/L?
One millimole per liter equals 100 ppm and one milliequivalent per liter equals 50 ppm, both expressed as calcium carbonate. That lets lab results sit next to municipal reports in the same unit.
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/conv/hardness-conversion \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"value":100,"from":"ppm","to":"gpg"}'const res = await fetch("https://api.kit.forhosting.com/conv/hardness-conversion", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"value": 100,
"from": "ppm",
"to": "gpg"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/conv/hardness-conversion",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"value": 100,
"from": "ppm",
"to": "gpg"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/conv/hardness-conversion", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"value":100,"from":"ppm","to":"gpg"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"value":100,"from":"ppm","to":"gpg"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/conv/hardness-conversion", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"value": 100,
"from": "ppm",
"to": "gpg"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "conv.hardness_conversion",
"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.
Limits
max_abs_value | 1000000000000 |
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
Everyday aliases such as mg/L, gpg, grains, °dH, °fH, and Clark are accepted so lab printouts, softener manuals, and spreadsheet cells share one contract.
What hardness conversion returns and which units it understands
Hardness conversion answers a reporting question, not a treatment question: given a hardness magnitude in one laboratory or plumbing unit, what is the equivalent magnitude in another unit that a municipal certificate, softener table, or export datasheet actually uses. This calculator accepts a finite non-negative value, a source unit, and a target unit, then returns the converted result rounded to a stable precision, the canonical from and to identifiers, human-readable labels, the intermediate value in parts per million as calcium carbonate, and the published factors for grains per gallon and each degree scale. Everyday spellings such as mg/L, grains per gallon, °dH, °fH, Clark, mmol/L, and meq/L normalize to those identifiers so forms, query strings, and spreadsheets can share one contract without private enums. Canonical identifiers are ppm for parts per million, mg_l for milligrams per liter, gpg for grains per US gallon, dh for German degrees, fh for French degrees, eh for English Clark degrees, mmol_l for millimoles per liter, and meq_l for milliequivalents per liter. There is no temperature correction and no soft-versus-hard classification: the engine either multiplies and divides by the documented ppm factors inside the supported magnitude range or rejects the input with invalid_input. Rejected cases include a missing value, from, or to field; non-finite numbers; magnitudes above the documented ceiling; negative hardness; and any target unit that is unsupported.
How the ppm bridge is applied and how results stay reproducible
Optional scientific notation on the value string is allowed when it parses as a finite decimal; embedded spaces, hex prefixes, and non-numeric tokens are rejected with a clear message so a bad cell does not become a wrong softener setpoint. Zero is a valid value and simply yields zero in the target unit. Computation multiplies value by the source factor in parts per million, then divides by the target factor: one grain per gallon is 17.1 ppm, one German degree is 17.8 ppm, one French degree is 10 ppm, one Clark degree is 14.3 ppm, one millimole per liter is 100 ppm, and one milliequivalent per liter is 50 ppm, while ppm and mg/L share a one-to-one ratio. One hundred parts per million therefore becomes one hundred divided by 17.1 grains per gallon, and ten German degrees becomes ten times 17.8 divided by ten French degrees. The preferred fields are value for the hardness magnitude, from for the source unit, and to for the target unit, with aliases amount, hardness, n, quantity, and level for the value, unit, from_unit, source, and input_unit for from, and target, to_unit, output_unit, and into for to so heterogeneous clients can share one contract. Negative values fail with invalid_input because physical hardness cannot be negative. An optional precision field, with aliases decimals and dp, chooses how many decimal places to expose for value, result, and value_ppm, defaulting to ten and capped at fifteen so JSON goldens stay stable. Pair the free browser run on this page with the priced API when you need the identical mathematical result inside an automated pipeline without re-implementing unit tables yourself.
Where hardness conversion fits in plumbing, labs, and software
On this page the work runs entirely in your browser; through the API each successful lookup costs $0.002, failed validation is not charged, and nothing is stored after the response returns. That split — free interactive exploration and a priced, identical API — matches the rest of the KIT tier-A catalog and lets you move from a classroom demo to an automated pipeline without changing the mathematical result.
Integration use cases
Homework, tutoring software, and CI fixtures
Generate reproducible hardness conversion results for worksheets and unit tests that assert the published 17.1 gpg, 17.8 °dH, 10 °fH, and 14.3 Clark factors.
Technical questions
How is hardness conversion billed on this page and via the API?
It is free in your browser on this page. Through the API a successful request costs $0.002; invalid inputs are not charged.
Which source and target units can I convert between?
Parts per million (ppm), milligrams per liter (mg_l), grains per US gallon (gpg), German degrees (dh), French degrees (fh), English Clark degrees (eh), millimoles per liter (mmol_l), and milliequivalents per liter (meq_l). Common aliases such as mg/L, grains, °dH, °fH, and Clark are accepted.