A while back I was building a personal calorie tracker and hit a wall: I needed an API that could look at a photo of food and return structured nutritional data. After months of experimenting with existing solutions — too expensive, too inaccurate, or barely documented — I ended up building my own.
This is that API: CaloAI. In this tutorial I'll show you how to integrate it in minutes.
What CaloAI does
Send a photo of any meal. Get back a clean JSON with:
- Calories, proteins, fats, carbs
- A health score (1–10)
- (PRO) Detected dish components, allergen alerts, diet tags (keto, vegan, low-carb), AI nutritionist verdict, and a confidence score
Everything is powered by Google Gemini 3.5 Flash under the hood, with a built-in caloric consistency check — meaning macros always add up mathematically (Calories = Protein×4 + Carbs×4 + Fat×9), no hallucinated numbers.
Setup
That's it. One endpoint: POST https://caloai.p.rapidapi.com/v1
Request structure
| Field | Type | Required | Description |
|---|---|---|---|
image_url |
string | ✅ | Publicly accessible URL of the food photo |
extra |
string | ❌ | Optional context — weight, meal type, hidden ingredients |
The extra field is a secret weapon. If your user knows something the camera can't see ("exactly 300g, added olive oil"), pass it here and the model treats it as ground truth — dramatically improving accuracy.
Python example
import requests
url = "https://caloai.p.rapidapi.com/v1"
headers = {
"x-rapidapi-key": "YOUR_API_KEY",
"x-rapidapi-host": "caloai.p.rapidapi.com",
"Content-Type": "application/json"
}
payload = {
"image_url": "https://example.com/my-lunch.jpg",
"extra": "Weight is around 300g, added olive oil" # optional
}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
r = data["response"]
print(f"Calories: {r['calories']} kcal")
print(f"Protein: {r['proteins']}g | Carbs: {r['carbs']}g | Fat: {r['fats']}g")
print(f"Health score: {r['healthy_points']}/10")
Response (Basic plan):
{"status":"success","response":{"proteins":38,"fats":52,"carbs":20,"calories":652,"healthy_points":3}}
JavaScript example
const response = await fetch("https://caloai.p.rapidapi.com/v1", {
method: "POST",
headers: {
"x-rapidapi-key": "YOUR_API_KEY",
"x-rapidapi-host": "caloai.p.rapidapi.com",
"Content-Type": "application/json"
},
body: JSON.stringify({
image_url: "https://example.com/breakfast.jpg"
})
});
const { response: data } = await response.json();
console.log(`${data.calories} kcal — Health: ${data.healthy_points}/10`);
Unlocking PRO features
On PRO, ULTRA, or MEGA plans the response expands with deeper analytical fields — ready to plug straight into your UI without extra processing:
{"status":"success","response":{"proteins":38,"fats":52,"carbs":20,"calories":652,"healthy_points":3,"confidence_score":95,"detected_dishes":["fried eggs","crispy bacon","cheddar cheese"],"diet_tags":["keto-friendly","low-carb"],"potential_allergens":["eggs","dairy"],"ai_verdict":"A solid high-protein option, but quite high in saturated fats. Consider pairing with fresh vegetables next time."}}
| Field | What it's useful for |
|---|---|
confidence_score |
Show a data quality indicator in your UI |
detected_dishes |
Break down mixed plates into components |
diet_tags |
Filter meals by dietary preference |
potential_allergens |
Safety warnings for your users |
ai_verdict |
Ready-to-display copy, no prompt engineering needed |
Real example: daily meal logger
Here's a minimal script that analyzes multiple meals and sums up daily totals:
import requests
def analyze_meal(image_url, extra=None):
headers = {
"x-rapidapi-key": "YOUR_API_KEY",
"x-rapidapi-host": "caloai.p.rapidapi.com",
"Content-Type": "application/json"
}
payload = {"image_url": image_url}
if extra:
payload["extra"] = extra
r = requests.post("https://caloai.p.rapidapi.com/v1", json=payload, headers=headers)
return r.json()["response"]
meals = [
("https://example.com/breakfast.jpg", "oat porridge with banana"),
("https://example.com/lunch.jpg", None),
("https://example.com/dinner.jpg", "about 400g"),
]
totals = {"calories": 0, "proteins": 0, "carbs": 0, "fats": 0}
for image_url, context in meals:
result = analyze_meal(image_url, context)
print(f"✓ {result['calories']} kcal | Health: {result['healthy_points']}/10")
for key in totals:
totals[key] += result[key]
print(f"\n📊 Daily totals:")
print(f" Calories: {totals['calories']} kcal")
print(f" Protein: {totals['proteins']}g | Carbs: {totals['carbs']}g | Fat: {totals['fats']}g")
Error handling
The API returns clear error messages:
response = requests.post(url, json=payload, headers=headers)
data = response.json()
if data["status"] == "error":
print(f"Error: {data['error']}")
else:
result = data["response"]
# process result...
Common errors:
-
403— missingimage_urlfield -
403— malformed or inaccessible image URL (make sure the URL is publicly accessible)
Tips
- Better photos = better results. Single dish, good lighting, top-down angle works best.
-
Use
extrawhenever you can. Even rough context like "about 300g" or "added butter" improves accuracy. -
healthy_pointsranges from 1 (deep-fried, highly processed) to 10 (whole foods, lean protein, nutrient-dense). Great for gamification in fitness apps. -
ai_verdictis UI-ready copy — no need to write prompts yourself, just render it directly.
Wrap up
That's one endpoint, a couple of headers, and you've got AI food recognition in your app.
If you're building something with CaloAI — a calorie tracker, fitness dashboard, smart food diary — I'd love to hear about it in the comments.