Open a food label in the EU and you see kilojoules. Open one in the US and you see Calories. They are the same quantity in different units, and the conversion factor is a constant that most implementations get subtly wrong — or worse, get right and then round at the wrong place.

The units

A kilocalorie (kcal) is 1000 small calories. A kilojoule (kJ) is 1000 joules. The exact conversion is defined by the heat capacity of water:

$$1\ \text{kcal} = 4.184\ \text{kJ}$$

So:

$$\text{kcal} = \frac{\text{kJ}}{4.184}, \qquad \text{kJ} = 4.184 \times \text{kcal}$$

The number 4.184 is exact by definition (the International Table calorie). It is not 4.2, and using 4.2 is a real error — 0.4% on every label.

const KJ_PER_KCAL = 4.184; function kjToKcal(kj) { if (!Number.isFinite(kj) || kj < 0) return NaN; return kj / KJ_PER_KCAL; } function kcalToKj(kcal) { if (!Number.isFinite(kcal) || kcal < 0) return NaN; return kcal * KJ_PER_KCAL; } 

Worked example

A label says 230 kcal per serving.

$$\text{kJ} = 230 \times 4.184 = 962.32$$

So the label reads "962 kJ" — and if it rounds to the nearest 10 kJ, "960 kJ". That rounding is where most disputes start.

Now the reverse: a label says 2,400 kJ per 100 g.

$$\text{kcal} = \frac{2400}{4.184} = 573.6$$

So 574 kcal per 100 g. A user who divides by 4.2 instead gets 571.4 — three kcal off per 100 g, and the error compounds across a full day of tracking.

Edge cases that actually bite

Rounding to the label increment. EU labels round energy to the nearest 1 kJ or 1 kcal; US labels round to the nearest 10 kcal above 50 kcal. If you compute from a rounded label value, the reverse conversion is off by up to half the increment. Convert the unrounded value, then round once for display.

"Calories" vs "kilocalories". On US labels, "Calorie" with a capital C means kilocalorie. In code, name the unit explicitly: kcal, not cal, and never Cal as a variable. A cal field that actually holds kcal is a latent bug.

Large values and floating point. At 10,000 kcal, 10000 * 4.184 is exact in IEEE 754 (41840). At 0.1 kcal, 0.1 * 4.184 = 0.41840000000000005. Round for display, not for storage.

Negative or zero energy. Zero is legal (water, black coffee). Negative is not. Reject negative input rather than returning a negative energy value that propagates into a daily total.

Atwater factors. The 4/4/9 rule (protein 4, carbohydrate 4, fat 9 kcal/g) is an approximation. Fiber is often counted as 2 kcal/g or excluded entirely depending on jurisdiction. If you derive kJ from macronutrients rather than from a stated energy value, you are computing a different number than the label's, and you should label it as such.

Common mistakes

  • Using 4.2 instead of 4.184. It is an approximation that is wrong by 0.4% on every conversion.
  • Converting through small calories. 1 kcal = 1000 cal, so 1 cal = 4.184 J. Going through small calories adds a factor of 1000 that is easy to drop.
  • Rounding before converting. Round only the final displayed value, never the intermediate.
  • Treating kJ and kcal as interchangeable in a database. Store one canonical unit and convert at the boundary; storing both invites drift.
  • Assuming the US label is in kcal when the field is named cal. It is. Rename the field.

Checking your own numbers

If you want to see the conversion for a label value — and the effect of the 4.184 factor against the 4.2 shortcut — the kJ to calories converter at https://www.miryori.org/tools/kj-calories-calculator shows both directions with the exact factor.

YMYL note: energy values are nutritional estimates, not medical advice. Label regulations differ by jurisdiction; verify against the specific rules that apply to your product.