Hair porosity estimate from a float test result
A clean strand that sinks fast in a glass of water points to high porosity: moisture gets in quickly and escapes just as fast, so layer moisture and seal it with oils or butters. Sinks slow means normal; floats means low. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Result
- sinks fast
- Porosity
- high
A hair porosity estimator turns the outcome of a simple water float test into a useful classification. In the float test, a clean strand of hair is placed in a glass of water: if it sinks fast the hair tends to be high porosity, if it sinks slow it is usually normal porosity, and if it floats it is typically low porosity. Enter what your strand did and this tool returns the porosity class, a plain-language summary of what it means for the hair cuticle, and a list of general care implications such as sealing moisture, using protein, or clarifying buildup.
What the float test measures and how it is read
Hair porosity describes how easily water and products pass through the cuticle, the outermost layer of overlapping cells on each strand. The float test is the most popular at-home way to get a rough read on it: take a clean, product-free strand of shed hair, let it sit a moment so surface tension settles, and drop it into a glass of room-temperature water. Watch what happens over a couple of minutes.
A strand that sinks fast to the bottom absorbed water readily, which suggests raised or damaged cuticles and therefore high porosity. A strand that sinks slow, drifting down gradually or hovering mid-glass, suggests a balanced cuticle and normal porosity. A strand that floats at the surface repelled the water, which points to flat, tightly closed cuticles and low porosity.
The test is a heuristic, not a lab measurement: oils, conditioners, or hard-water residue on the strand can skew the result, which is why the strand should be freshly washed and fully dried first. This capability takes the observed outcome of that test, normalizes the wording, and maps it to the standard three-class interpretation used in hair care guidance.
Using the classification in a care routine
The classification matters because the three porosity classes respond differently to the same products. High porosity hair takes moisture in quickly but loses it just as fast, so the practical advice centers on layering moisture and then sealing it with oils or butters, using periodic protein treatments to help patch gaps in the cuticle, favoring leave-in conditioners, limiting heat and chemical processing, and rinsing cool to help the cuticle lie flatter.
Normal porosity hair is the balanced case: regular conditioning with occasional deep treatments, tolerance for both lightweight and richer products, and protection from cumulative damage to keep it that way. Low porosity hair resists absorption, so products should go onto damp, warm hair, lightweight water-based formulas beat heavy butters that sit on the surface, gentle heat during deep conditioning helps open the cuticle, and occasional clarifying removes the buildup that accumulates because little is absorbed.
Treat the result as a starting hypothesis: porosity can vary along one head of hair and changes with damage over time, so re-testing periodically and combining this signal with how the hair actually behaves under products gives the most reliable routine.
What you can do with it
Interpret a float test at home
After dropping a clean strand into a glass of water, enter what it did and get the standard high, normal, or low porosity reading without memorizing the mapping.
Build a starter care routine
Use the returned care implications as a checklist for choosing product weight, protein use, sealing oils, heat habits, and clarifying frequency for your porosity class.
FAQ
What inputs does the estimator accept?
Case, hyphens, underscores, and common phrasings like 'sank quickly' or 'stays on top' are normalized automatically.
What does each float test outcome mean?
Sinks fast maps to high porosity (raised cuticle absorbs water quickly), sinks slow to normal porosity (balanced absorption), and floats to low porosity (tight cuticle repels water).
What happens on an unrecognized result?
Unrecognized results are never charged and are never guessed.
Is the float test accurate?
It is a heuristic, not a lab measurement. Residue from products or hard water can skew it, so test with a clean, fully dried strand and treat the classification as a starting point for a routine.
Is the hair porosity estimator free?
The browser tool is free and runs locally.
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/beauty/hair-porosity-estimate \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"result":"sinks fast"}'const res = await fetch("https://api.kit.forhosting.com/beauty/hair-porosity-estimate", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"result": "sinks fast"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/beauty/hair-porosity-estimate",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"result": "sinks fast"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/beauty/hair-porosity-estimate", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"result":"sinks fast"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"result":"sinks fast"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/beauty/hair-porosity-estimate", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"result": "sinks fast"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "beauty.hair_porosity_estimate",
"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
Results the tool does not recognize are rejected with invalid_input instead of being guessed.
How to call the API and what comes back
Matching is forgiving about presentation: case is ignored, hyphens and underscores are treated as spaces, repeated spaces are collapsed, and common phrasings such as sank quickly, floats, stays on top, or simply fast, slow, and float resolve to the canonical outcomes. Send a JSON body with the result field set to what the strand did, for example result equals sinks fast, sinks slow, or floats. The aliases outcome and behavior are also accepted. Anything else returns invalid_input, which is never charged, rather than a guessed classification. On success the response contains result with the canonical outcome, porosity with the class high, normal, or low, a summary sentence explaining the cuticle behavior behind the class, care_implications as an ordered list of general care guidance, a short message, and a steps array showing the normalization and classification rule that was applied. Pricing is a flat $0.002 per successful request with unit item and zero marginal unit price.
Integration use cases
Power a beauty quiz or content site
Integrate the API behind a float-test questionnaire so users get a deterministic, consistent porosity classification and explanation from free-text answers.