Food Portion Size Calculator API: Scale Nutrition to Any Serving in One Call
Published June 15, 2026
A food portion size calculator API takes a food ID and a gram amount and returns calories, protein, carbohydrates, fat, fiber, and other macros for exactly that serving, no client-side math required. Instead of fetching per-100g data and multiplying by a fraction in every view, you call one endpoint and render the result.
This pattern is especially valuable for meal logging apps where users pick a food, enter their portion in grams, and expect the macro display to update instantly and accurately.
The Endpoint
GET /api/v1/public/calc/portion
Parameters:
| Parameter | Type | Example | Notes |
|---|---|---|---|
food_id | integer | 12345 | From /search/foods or /foods/{id} |
grams | float | 150 | Serving size in grams (0 < grams ≤ 5000) |
Quick Start
First, find a food ID via search:
curl "https://api.calorieapi.com/api/v1/public/search/foods?q=chicken+breast&limit=1"
Then scale it to your serving:
curl "https://api.calorieapi.com/api/v1/public/calc/portion?food_id=12345&grams=200"
Response:
{
"food_id": 12345,
"food_name": "Chicken breast, raw",
"requested_grams": 200,
"nutrition": {
"calories": 240.0,
"protein_g": 44.0,
"carbohydrates_g": 0.0,
"fat_g": 5.0,
"fiber_g": 0.0,
"sugars_g": 0.0,
"saturated_fat_g": 1.4,
"sodium_g": 0.14
}
}
All fields are already scaled to the requested gram amount. calories is the energy for exactly 200 g of chicken breast — not per 100 g.
Why Offload the Scaling Math
Doing (grams / 100) × nutrient_per_100g in client code is trivial but error-prone at scale:
- Different platforms round floating-point differently
- Each client must implement and test the same formula
- Nutrient fields may be
null— division by zero edge cases accumulate - A backend formula update requires releasing all clients simultaneously
Centralising this in the API keeps all clients consistent and lets you improve accuracy without a client release.
Building a Portion Picker in React
import { useState, useCallback } from 'react'
function PortionPicker({ food }) {
const [grams, setGrams] = useState(100)
const [nutrition, setNutrition] = useState(null)
const fetchNutrition = useCallback(async (amount) => {
const res = await fetch(
`https://api.calorieapi.com/api/v1/public/calc/portion?food_id=${food.id}&grams=${amount}`
)
if (!res.ok) return
const data = await res.json()
setNutrition(data.nutrition)
}, [food.id])
return (
<div>
<label>
Grams
<input
type="number" value={grams} min={1}
onChange={e => { setGrams(e.target.value); fetchNutrition(e.target.value) }}
/>
</label>
{nutrition && (
<dl>
<dt>Calories</dt><dd>{nutrition.calories} kcal</dd>
<dt>Protein</dt><dd>{nutrition.protein_g} g</dd>
<dt>Carbs</dt><dd>{nutrition.carbohydrates_g} g</dd>
<dt>Fat</dt><dd>{nutrition.fat_g} g</dd>
</dl>
)}
</div>
)
}
Debounce the onChange handler by 200–300 ms to avoid a request on every keystroke.
Common Serving Presets
Most users pick from a fixed list rather than typing a gram value. Map common serving descriptions to grams before calling the endpoint:
const SERVING_PRESETS = {
'1 cup': 240,
'1/2 cup': 120,
'1 tbsp': 15,
'1 tsp': 5,
'100g': 100,
'1 oz': 28,
'1 medium': 150,
'1 large': 200,
}
const grams = SERVING_PRESETS[selectedServing] ?? parseFloat(customGrams)
Pass the resolved grams value to the portion endpoint.
Null Fields
Some foods lack complete nutrient coverage. The nutrition object omits fields with no data (they appear as null). Handle this gracefully:
const display = (value, unit) =>
value != null ? `${value} ${unit}` : '—'
console.log(display(nutrition.fiber_g, 'g')) // "3.2 g" or "—"
Caching Strategy
The portion endpoint is deterministic: the same food_id + grams always returns the same result (until the underlying food record is updated). You can safely cache responses in memory or localStorage:
const cache = new Map()
const key = `${foodId}:${grams}`
if (!cache.has(key)) {
const result = await fetchPortion(foodId, grams)
cache.set(key, result)
}
return cache.get(key)
For high-traffic apps, set a 24-hour TTL to pick up any food data corrections.
Related Guides
Frequently Asked Questions
What does a food portion size calculator API do?
It takes a food ID and a gram amount and returns exact calories, protein, carbohydrates, fat, and other macros scaled to that specific serving — eliminating client-side nutrient scaling math.
How do I get a food ID to use with the portion endpoint?
Search for the food using GET /search/foods and use the id field from the result. Store the id after the first lookup to skip repeat searches.
What units does the portion endpoint accept?
The endpoint accepts grams only. For recipes using cups, tablespoons, or ounces, convert to grams using a unit conversion table before calling the endpoint.
Are null nutrition fields safe to use?
Yes. Some foods lack complete nutrient coverage. Treat null fields as unknown rather than zero, and show a dash or 'N/A' in the UI rather than displaying zero.
Can I cache portion API responses?
Yes. Responses are deterministic for the same food_id and grams. Cache with a 24-hour TTL to stay current with food data updates while reducing API calls.
