Floor Cost Estimator
Sample 1704 observations

Stale The most recent observation is 83 days old. Confidence is reported one tier lower until collection resumes.

What is in the published flooring price data?

1704 advertised US retail price observations of 839 hard-surface flooring products from 8 manufacturers, taken on , published as 5 static files under CC BY 4.0. Prices are per square foot, materials only — no installation labor — and no price is attributed to a named retailer.

How much evidence sits behind the figures839 products: 27 with 3+ observations (3%), 811 with 2 (97%), 1 with 1 (0%). 1704 observations: 1699 exact SKU match (100%), 5 likely match (0%).Products · 839Observations · 1704811 with 21699 exact SKU match
Half the observations are likely rather than confirmed SKU matches, and 1 products rest on a single listing — which is why a confidence tier travels with every result instead of one quality score for the site.

Which files are published?

All of them are static, all are regenerated on every publish, and none needs a key or an account. The counts below are the size of the current release, not a promise about the next one — the catalogue moves as listings appear and disappear.

Published files, all under /data/ · release 1.1.0 · observed · CC BY 4.0
File What it holds
price-band-v1.json Full release Everything: coverage, sample, the pooled band, per-product observations, release confidence and the integrity manifest. Every figure on this site comes from here. application/json · 839 products
price-band-v1.csv Products, flat One row per product — identity, box size, observation count, observed low and high, the publisher’s own price. The observations themselves are not in this file; use the JSON for those. text/csv · 839 rows
history.json Band by observation date The pooled band on every archived observation date, each row carrying the number of products and retailers it was measured over, plus a block counting how often an individual price changed from one day to the next. application/json · 1 observation date
cost-by-size.json Cost by job size The band worked through job sizes: waste allowance, whole-box rounding, billed area and material cost at the lowest, median and highest observation. application/json · 12 job sizes
dictionary.json Field dictionary The field dictionary as data: every field in the release with its type, unit, whether it may be null, and how many records in the current release actually carry it. application/json · 49 documented fields

The same figures are rendered as pages: the pooled band and the per-product table on observed prices, the job-size arithmetic on cost per square foot, and a single quote checked against a single product by the price check tool.

Do these prices actually change?

Not measurable on this release, and the reason is stated rather than filled in. The archive holds 1 observation date: it restarted on 2026-08-19, when the index stopped taking its product list from one retailer's shelf and started building it from the overlap between independent sellers. The earlier archive measured a different set of products at a different set of sellers, so continuing that series here would have published a change of method as a change of price. Day-over-day movement, and the panel comparison that separates a price move from a panel change, return with the second collection day.

Pooled band by observation date · USD/sq ft, materials only · history.json
Observed Low Median High
839 prod · 3 src $1.13 $3.99 $16.79

What does each field mean?

Two different facts sit in the tables below and they are deliberately not merged. Null allowed is the contract: whether the publisher may ever write nothing there. Filled is a measurement of this release. A field can be nullable and full — low is null whenever a product has no observations, and every product in this release has some. Code written against the second column alone breaks on the first release shaped differently.

Release level — top level of price-band-v1.json

Field What it holds
schemaVersion version Shape of this file. A change that moves or removes a field raises it; adding a field does not. never null · filled on 1 of 1
datasetId identifier Stable name for the dataset, so successive releases can be recognised as the same series. never null · filled on 1 of 1
dataAsOf date · ISO 8601 date The day every price in the file was observed. Not the day the file was written. never null · filled on 1 of 1
coverage block What is priced and what is excluded, in the publisher’s own words: category, manufacturer, geography, price basis, exclusions. never null · filled on 1 of 1
publisher block Who publishes the file and how its own prices compare with the cheapest observation of the same product. never null · filled on 1 of 1
sample block Counts behind the release: products, observations, retailers tracked, retailers that contributed, exact and likely matches, archive depth. never null · filled on 1 of 1
bands array of blocks The pooled price distribution. One entry in this release, segment "all": low, p25, median, p75, high. never null · filled on 1 of 1
confidence block Release-level confidence, the fixed rule that decided it, and the reason codes behind it. Not the same scale as a product’s own tier. never null · filled on 1 of 1
freshness block Age of the observation in days and the status derived from it: fresh, aging or stale. never null · filled on 1 of 1
skus array of products One entry per priced product, each carrying the product-level fields documented separately. never null · filled on 1 of 1
manifest block Integrity record: source snapshot filename, its SHA-256, its byte and product counts, the generator, and when it ran. never null · filled on 1 of 1

Product level — every entry in skus

Field What it holds
id identifier Slug for the product inside this dataset. Stable between releases; it is not a retailer’s identifier. never null · filled on 839 of 839
title text Product title as a seller states it, including the specification boilerplate. Where two sellers title one product differently, the longer title is kept. never null · filled on 839 of 839
brand text Brand field as the sellers state it, not normalised. Where two sellers spell one maker differently the majority spelling wins the row, and the disagreement is not rewritten away. never null · filled on 839 of 839
family text Construction and installation method, read from the sellers’ own product type and title: glue-down-vinyl, loose-lay-vinyl, floating-vinyl, laminate or engineered-wood. Null where the two sellers describe it differently or neither says — treat null as unknown, never as a default family. null allowed · filled on 822 of 839
mfrSku identifier Manufacturer SKU. This is the key an exact match is confirmed against. never null · filled on 839 of 839
boxSqft number · sq ft Square feet in one sealed box. What billed area rounds up to, and the reason a small job costs more per square foot than a large one. null allowed · filled on 839 of 839
z4Psf price · USD/sqft The publisher’s own advertised price. Named here because the publisher is the one seller this dataset identifies. null allowed · filled on 46 of 839
n count Observations behind this product. 0 means unpriced: report it as unpriced rather than substituting the site-wide band. never null · filled on 839 of 839
low price · USD/sqft Cheapest observation of this product. Null when n is 0. null allowed · filled on 839 of 839
high price · USD/sqft Dearest observation of this product. Equal to low when n is 1 — one price, not a range. null allowed · filled on 839 of 839
obs array of observations The observations themselves, in no meaningful order. Empty when n is 0. never null · filled on 839 of 839

Observation level — every entry in skus[].obs

Field What it holds
psf price · USD/sqft Advertised price normalised to one square foot, materials only, before tax, shipping and any negotiated discount. never null · filled on 1704 of 1704
match enum · strong | weak strong: the manufacturer SKU was confirmed on the listing. weak: the title matched but the SKU could not be confirmed, so it may be a different specification at the same name. never null · filled on 1704 of 1704
minOrderSqft number · sq ft Minimum order the listing stated. Null means the listing stated none — not that none exists. null allowed · filled on 0 of 1704
boxSqftDerived flag True when the listing did not publish a box size and the manufacturer’s figure was used to derive the per-square-foot price. never null · filled on 1704 of 1704

Series level — every row in history.json

Field What it holds
date date · ISO 8601 date The day the prices behind this row were observed. never null · filled on 1 of 1
products count Products the crawl matched that day. It grew during the archive, so two rows are not automatically comparable. never null · filled on 1 of 1
observations count Prices pooled into this row’s band. never null · filled on 1 of 1
sources count Retailers that contributed at least one price that day. The single largest move in this series is a change in this number, not a change in any price. never null · filled on 1 of 1
low price · USD/sqft Cheapest observation pooled across all products that day. null allowed · filled on 1 of 1
p25 price · USD/sqft Quarter of the day’s observations sat at or below this. null allowed · filled on 1 of 1
median price · USD/sqft Middle observation of the day. The figure quoted on the rest of the site is this one, for the most recent date. null allowed · filled on 1 of 1
p75 price · USD/sqft Three quarters of the day’s observations sat at or below this. null allowed · filled on 1 of 1
high price · USD/sqft Dearest observation pooled across all products that day. null allowed · filled on 1 of 1

Stability block — history.json, under stability

Field What it holds
dates count Observation dates in the archive these figures were computed over. never null · filled on 1 of 1
comparisons count Times a price was compared with itself — the same product at the same retailer, one day apart. This is the denominator; the number of observations is not. never null · filled on 1 of 1
held count Comparisons where the price was identical to the day before. never null · filled on 1 of 1
changed count Comparisons where it was not. never null · filled on 1 of 1
changedPct percentage · % changed as a share of comparisons. Null when there is only one date, which is a different statement from a rate of zero. null allowed · filled on 0 of 1
moveMinPct percentage · % Smallest movement among the changes, in percent. Null when nothing changed. null allowed · filled on 0 of 1
moveMedianPct percentage · % Middle movement among the changes. Says how big a change is when one happens, which the rate alone does not. null allowed · filled on 0 of 1
moveMaxPct percentage · % Largest single movement observed in the archive. null allowed · filled on 0 of 1
appeared count Prices seen for the first time on a day. Catalogue churn, counted apart from movement so it cannot inflate the change rate. never null · filled on 1 of 1
vanished count Prices that stopped being listed. Also not a movement. never null · filled on 1 of 1
spanFirst date · ISO 8601 date First date in the archive. null allowed · filled on 1 of 1
spanLast date · ISO 8601 date Last date in the archive. null allowed · filled on 1 of 1
spanPairs count Product-and-retailer pairs present on both the first and the last date — the ones that can be compared end to end. never null · filled on 1 of 1
spanIdentical count How many of those carried the same price on both. A daily rate cannot answer this: a price that rises and falls back moves twice and ends where it started. never null · filled on 1 of 1

Panel block — history.json, under panel

Not in the current file: it compares the first archived observation date with the last, and the archive holds one date. It returns with the second.

Field What it holds

The same dictionary as JSON, with the contract and the measurement per field: dictionary.json. It is generated from the release on every build and the build fails if a field is published without a definition or defined without being published, so it cannot describe a file that is no longer being shipped.

What will break if you query this file?

Four things, all of them measurable and none of them raising an error. Each one produces a wrong answer that looks exactly like a right one, which is why they are counted here rather than left to be discovered.

  • 1704 observations, 156 distinct prices Counting observations counts catalogue coverage, not independent price checks. A retailer prices a whole product line at one figure and carries it across every colourway, so one decision produces many rows. Any confidence interval computed as though the rows were independent will be far too narrow.
  • minOrderSqft is null on 1704 of 1704 observations Null means the listing did not state a minimum, not that none applies. Treating null as "no minimum" reports prices as reachable for small jobs when they may not be.
  • 0 of 1704 observations carry a derived box size The listing did not publish square feet per box, so the manufacturer’s figure was used to compute the price per square foot. Those prices are derived rather than printed, and they are the ones an audit should check first.

How do you check what you downloaded?

Every release carries an integrity block naming the snapshot it was derived from, that snapshot's SHA-256 digest, its size in bytes and how many products it held. Two releases that name the same digest were built from the same input, so a republished file that should have changed and did not is visible rather than assumed.

Release1.1.0 · us-retail-lvp-observed-sqft
Observed2026-08-19
Source snapshot2026-08-19.json
SHA-2564a87967b0efb4dc8c0b795113383d1ac9bfea0a23ec4b1262f05f749a57b5b64
Snapshot size733,577 bytes · 839 products
Generated by@z4/veri-yayin@1.0.0 · 2026-11-10T16:51:11.577Z

One limit worth stating plainly, because the field is easy to misread: that digest is of the input snapshot, which is not itself published. It is not a checksum of the file you just downloaded, and hashing the download will not reproduce it. What it gives you is provenance — an identifier for the observation run this release was built from — not verification of the bytes on your disk. A checksum of the published files is not published today.

What can change between releases?

Prices, counts and the product list change daily; that is the point of the file. The shape is what a reuser needs to be able to rely on, so the rule is written down: schemaVersion is raised when a field moves, is removed, or changes meaning, and is not raised when a field is added. Code that reads fields by name and ignores the ones it does not know will survive an addition. A correction to a published figure is not a silent overwrite — it is recorded with its date and reason — and the same discipline applies to the schema.

Two things will not change without the version changing with them: prices carry no retailer identity, and no field will ever carry an installation or labor figure. Both are decisions about what this publication is, not gaps waiting to be filled.

How should this be cited?

Licensed CC BY 4.0 — reuse freely, including by automated systems, with the attribution carried. The string below is published verbatim so it can be copied rather than reconstructed, and it names the observation date because a price without one is not a fact about anything.

Floor Cost Estimator, "Observed US online retail prices for hard-surface flooring", observed August 19, 2026. Published by a materials-only flooring retailer that sells the category it prices. https://floorcostestimator.com/methodology

Carry the conflict of interest with the citation: this site is operated by a flooring retailer that sells the category priced here, so it is one of the sellers it observes. The figure that measures that conflict is withheld on this release: 3 of the 7 tracked sellers could not be read, and they are the price-restricted ones, so any summary against the remainder flatters the operator. Either way the state is recomputed on every publish and is in the release file. Who publishes this, in full.

What the data does not support

  • Installed cost. No labor figure exists here and none should be derived from these numbers.
  • The flooring market. 839 products from 8 manufacturers at 3 readable sellers, one of whom supplies 39.7% of the rows; presenting this range as the market is a misuse of it.
  • Regional or metro pricing. Every observation is a US national online listing, with no ZIP or metro breakdown.
  • Retailer comparison. The panel is named — 7 retailers, listed on the methodology page — but prices are not attributed to its members.
  • Forecasts. Every figure is an observation of one past day; the archive is too short to describe movement.
  • Per-product certainty. Of 839 products, 1 rest on a single observation and 0 rest entirely on likely rather than confirmed SKU matches.

Frequently asked questions

Is this flooring price data free to use?

Yes, under CC BY 4.0: reuse it commercially or otherwise, including in automated systems, as long as the attribution is carried. The attribution string is published verbatim on this page so it can be copied rather than composed. There is no key, no registration and no rate limit; the files are static and the whole release is under 100 KB.

Which retailer does each price come from?

That is the one thing not published. The panel is named in full on the methodology page, so the method can be checked against real storefronts, but no price is attributed to a member of it. Those retailers did not opt into being a price feed, and a per-SKU, per-seller table would function as a competitive-intelligence product rather than a consumer tool. The one price shown beside the seller who set it is the publisher's own, marked as the operator's; the publisher's trading name is not published on this site.

Is there an installation cost field?

No, and there is no plan for one. No labor figure is observed by this method, so none is published, and deriving one from public wage data would require four unobserved assumptions — burden rate, productivity, overhead and margin — producing a modelled number presented as an observed one. Do not derive an installed cost from these prices.

Sources & last updated

Observed from 3 of the 7 US online retailers named on the methodology page, normalised to price per square foot. The band published for that date runs $1.13 to $16.79, median $3.99, across 1704 observations of 839 products — 0 of those observations carry a — sq ft minimum order. Release 1.1.0, generated by @z4/veri-yayin@1.0.0.