AI food apps may be underestimating your calories by hundreds, study finds
AI food apps may be underestimating your calories by hundreds, study finds
Listen to article
5 min listen
Audio reading is not supported on this browser.
Ready
Thanks for listening. Continue with a related story, or tap the speaker icon on the next page to listen
Can newly discovered soil fungus stop devastating African armyworm when chemicals have failed?
The Conversation
·
53 minutes agoRead nextOpens a fresh page.
Researchers found popular AI food apps underestimated meal calories by 250 to 345 calories on average, raising concerns over their reliability for <a href="https://healthylife7.com/solving-the-mystery-of-why-blocking-and-stimulating-a-brain-receptor-helps-weight-loss/” title=”Solving the Mystery of Why Blocking and Stimulating a Brain Receptor Helps Weight Loss”>weight loss and diet management
Many people use AI-powered food apps to track what they eat and manage their weight. These apps promise a quick and easy way to count calories by simply taking a photo of a meal. However, new research suggests they may not always be as accurate as users expect.
Researchers found that four popular AI calorie-counting apps underestimated the calorie content of meals by an average of 250 to 345 calories. They also underestimated fat by about 30 grams per meal, meaning users could be consuming significantly more calories than they realise.
The findings were presented at NUTRITION 2026, the annual meeting of the American Society for Nutrition.
AI calorie-counting apps analyse a photo of a meal by identifying the foods on the plate, estimating portion sizes and comparing the information with nutrition databases to calculate calories, fat, carbohydrates and protein.
Although this process is much faster than manually entering every ingredient, the study found it does not always produce accurate results.
To assess the apps, researchers analysed 102 meals prepared in a research kitchen. Every ingredient was carefully weighed before cooking, allowing the team to determine the exact calorie and nutrient content of each meal.
Latest Stories
- Can newly discovered soil fungus stop devastating African armyworm when chemicals have failed?
- Court battle deepens over proposed Nairobi–Nakuru highway toll charges as KeNHA challenges COFEK suit
- Tana River, UNDP review food systems project amid food security and climate challenges
- UN report reveals 79 million Ethiopians face hunger as healthy food slips out of reach
All four apps underestimated the calorie and fat content of the meals, with some estimates falling short by more than 300 calories.
The apps were more accurate when estimating carbohydrates, but they still struggled to correctly calculate overall calories and fat.
“People should remember that photo-based food apps only provide estimates. The actual calorie and fat content of a meal may be much higher than what the app reports.”
The largest errors were recorded with ketogenic, or keto, meals, which are high in fat and low in carbohydrates.
Researchers believe the apps have difficulty recognising foods that contain large amounts of hidden fat, including butter, cooking oil, cheese, cream and sauces. These ingredients contribute substantial calories but are difficult for artificial intelligence to identify from a photograph.
Some apps also estimated larger meals more accurately than smaller ones, but none consistently produced accurate results across every meal tested.
The researchers said the findings are significant because millions of people now rely on AI-powered apps to lose weight, manage diabetes or improve their eating habits.
If an app underestimates calorie intake by several hundred calories each day, it could make it more difficult for users to lose weight or understand why they are not meeting their health goals.
Experts say AI food apps can still be valuable because they make tracking meals quicker and more convenient than recording them manually. However, they should be used as a guide rather than an exact measure of food intake.
“AI can help people keep track of their diet, but it should not replace healthy eating advice or careful portion control. The results should be seen as estimates, not exact numbers.”
The researchers also tested more than 200 additional meals to better understand why the apps performed well with some foods but poorly with others. Early findings suggest that high-fat foods remain the most challenging for AI to assess accurately.
They believe future advances in artificial intelligence could improve accuracy by helping the technology better recognise cooking oils, sauces and other ingredients that are often hidden in meals.
The team said more research is needed before people can rely on AI to accurately measure the nutritional value of food from photographs alone.
They also noted that the findings are preliminary because they were presented at a scientific conference and have not yet been published in a peer-reviewed medical journal.
For now, experts recommend using AI calorie-counting apps as a helpful tool rather than a definitive measure of calorie intake.
People who need to closely monitor their diet because of obesity, diabetes or other medical conditions should continue to follow advice from doctors or dietitians and pay close attention to portion sizes.
As artificial intelligence continues to advance, these apps are expected to become more accurate. Until then, users should remember that a photo of a meal does not always tell the full story, and the actual calorie content could be far higher than the app estimates.
Other Topics To Read
Top Stories Today
- KeNHA challenges COFEK suit over proposed A8 highway tolls
- New fungus discovery could transform fight against African armyworm
- Study warns AI calorie-counting apps get meal calories wrong
- Tana River, UNDP review food project to tackle hunger, climate crisis
- Boniface Mwangi wants corrupt officials sentenced to death
- Over 92 million Ethiopians cannot afford a healthy diet, UN warns
`;
}
return “;
}
function commentActionsMarkup(comment, canComment) {
const likeLabel = comment.liked_by_me ? ‘Liked’ : ‘Like’;
const likeCount = Number(comment.like_count || 0) > 0
? “
: ”;
const likeButton = canComment && comment.status === ‘approved’
? “
: “;
const replyButton = canComment && comment.status === ‘approved’
? “
: ”;
return `
`;
}
function commentMarkup(comment, canComment, isReply = false) {
const pendingBadge = comment.status && comment.status !== ‘approved’
? “
: ”;
const edited = comment.is_edited
? “
: ”;
const repliesHtml = Array.isArray(comment.replies) && comment.replies.length
? `
`
: “;
return `
`;
}
function replyFormMarkup(commentId) {
return `
`;
}
function setNotice(widget, message, type = ‘info’) {
const notice = widget.querySelector(‘[data-role=”notice”]’);
if (!notice) return;
if (!message) {
notice.hidden = true;
notice.textContent = ”;
notice.classList.remove(‘is-error’);
return;
}
notice.hidden = false;
notice.textContent = message;
notice.classList.toggle(‘is-error’, type === ‘error’);
}
function setCount(widget, total) {
const count = widget.querySelector(‘[data-role=”count”]’);
if (!count) return;
const num = Number(total || 0);
count.textContent = num === 1 ? ‘1 comment’ : `${num} comments`;
}
function openReplyBox(widget, commentId) {
widget.querySelectorAll(‘[data-role=”reply-box”]’).forEach(box => {
box.hidden = true;
box.innerHTML = ”;
});
const targetItem = widget.querySelector(`.ev-comments__item[data-comment-id=”${commentId}”]`);
if (!targetItem) return;
const replyBox = targetItem.querySelector(‘[data-role=”reply-box”]’);
if (!replyBox) return;
replyBox.hidden = false;
replyBox.innerHTML = replyFormMarkup(commentId);
const textarea = replyBox.querySelector(‘textarea’);
if (textarea) textarea.focus();
}
function closeReplyBox(container) {
if (!container) return;
container.hidden = true;
container.innerHTML = ”;
}
async function initCommentsWidget(widget) {
const state = {
articleId: Number(widget.dataset.articleId),
loadUrl: widget.dataset.loadUrl,
storeUrl: widget.dataset.storeUrl,
commentsBaseUrl: widget.dataset.commentsBaseUrl,
canComment: widget.dataset.canComment === ‘1’,
page: 1,
perPage: 10,
sort: ‘newest’,
total: 0,
hasMore: false,
busy: false
};
const list = widget.querySelector(‘[data-role=”list”]’);
const loading = widget.querySelector(‘[data-role=”loading”]’);
const empty = widget.querySelector(‘[data-role=”empty”]’);
const loadMoreBtn = widget.querySelector(‘[data-role=”load-more”]’);
const sortSelect = widget.querySelector(‘[data-role=”sort”]’);
const composerForm = widget.querySelector(‘[data-role=”composer-form”]’);
async function loadComments(reset = true) {
if (state.busy) return;
state.busy = true;
setNotice(widget, ”);
loading.hidden = false;
if (reset) {
state.page = 1;
list.innerHTML = ”;
empty.hidden = true;
}
try {
const url = new URL(state.loadUrl, window.location.origin);
url.searchParams.set(‘page’, state.page);
url.searchParams.set(‘per_page’, state.perPage);
url.searchParams.set(‘sort’, state.sort);
const response = await requestJson(url.toString(), {
method: ‘GET’,
headers: {
‘Accept’: ‘application/json’,
‘X-Requested-With’: ‘XMLHttpRequest’
}
});
const items = Array.isArray(response.data) ? response.data : [];
const meta = response.meta || {};
state.total = Number(meta.total || 0);
state.hasMore = !!meta.has_more;
setCount(widget, state.total);
if (reset) {
list.innerHTML = ”;
}
if (!items.length && reset) {
empty.hidden = false;
} else {
empty.hidden = true;
list.insertAdjacentHTML(
‘beforeend’,
items.map(item => commentMarkup(item, state.canComment, false)).join(”)
);
}
loadMoreBtn.hidden = !state.hasMore;
} catch (error) {
if (!list.children.length) {
empty.hidden = false;
empty.textContent = ‘Unable to load comments right now.’;
}
setNotice(widget, error.message || ‘Unable to load comments.’, ‘error’);
} finally {
loading.hidden = true;
state.busy = false;
}
}
async function submitTopLevelComment(form) {
const textarea = form.querySelector(‘textarea[name=”content”]’);
const button = form.querySelector(‘[data-role=”submit-comment”]’);
if (!textarea) return;
const content = textarea.value.trim();
if (!content) return;
const originalText = button ? button.textContent : ”;
try {
if (button) {
button.disabled = true;
button.textContent = ‘Posting…’;
}
const response = await requestJson(state.storeUrl, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({
article_id: state.articleId,
content: content,
source_url: window.location.href
})
});
textarea.value = ”;
if (response?.data) {
list.insertAdjacentHTML(
‘afterbegin’,
commentMarkup(response.data, state.canComment, false)
);
empty.hidden = true;
if ((response.data.status || ”) === ‘approved’) {
state.total += 1;
setCount(widget, state.total);
}
}
setNotice(widget, response.message || ‘Comment posted successfully.’);
} catch (error) {
setNotice(widget, error.message || ‘Unable to post comment.’, ‘error’);
} finally {
if (button) {
button.disabled = false;
button.textContent = originalText || ‘Post comment’;
}
}
}
async function submitReply(form) {
const commentId = Number(form.dataset.commentId || 0);
const textarea = form.querySelector(‘textarea[name=”content”]’);
const button = form.querySelector(‘.ev-comments__reply-submit’);
if (!commentId || !textarea) return;
const content = textarea.value.trim();
if (!content) return;
const originalText = button ? button.textContent : ”;
try {
if (button) {
button.disabled = true;
button.textContent = ‘Posting…’;
}
const response = await requestJson(`${state.commentsBaseUrl}/${commentId}/reply`, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({
article_id: state.articleId,
content: content,
source_url: window.location.href
})
});
if (response?.data) {
const parentItem = widget.querySelector(`.ev-comments__item[data-comment-id=”${commentId}”]`);
if (parentItem) {
const repliesWrap = parentItem.querySelector(‘.ev-comments__replies’);
if (repliesWrap) {
repliesWrap.insertAdjacentHTML(
‘beforeend’,
commentMarkup(response.data, state.canComment, true)
);
}
}
}
closeReplyBox(form.closest(‘[data-role=”reply-box”]’));
setNotice(widget, response.message || ‘Reply posted successfully.’);
} catch (error) {
setNotice(widget, error.message || ‘Unable to post reply.’, ‘error’);
} finally {
if (button) {
button.disabled = false;
button.textContent = originalText || ‘Post reply’;
}
}
}
async function toggleLike(button) {
const commentId = Number(button.dataset.commentId || 0);
if (!commentId) return;
const originalHtml = button.innerHTML;
try {
button.disabled = true;
button.innerHTML = ‘Working…’;
const response = await requestJson(`${state.commentsBaseUrl}/${commentId}/like`, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({})
});
const liked = !!response?.data?.liked;
const likeCount = Number(response?.data?.like_count || 0);
button.classList.toggle(‘is-liked’, liked);
button.innerHTML = `${liked ? ‘Liked’ : ‘Like’} ${likeCount > 0 ? “ : ”}`;
} catch (error) {
button.innerHTML = originalHtml;
setNotice(widget, error.message || ‘Unable to update like.’, ‘error’);
} finally {
button.disabled = false;
}
}
if (composerForm) {
composerForm.addEventListener(‘submit’, function (e) {
e.preventDefault();
submitTopLevelComment(composerForm);
});
}
if (sortSelect) {
sortSelect.addEventListener(‘change’, function () {
state.sort = this.value || ‘newest’;
loadComments(true);
});
}
if (loadMoreBtn) {
loadMoreBtn.addEventListener(‘click’, function () {
if (state.busy || !state.hasMore) return;
state.page += 1;
loadComments(false);
});
}
widget.addEventListener(‘click’, function (e) {
const likeBtn = e.target.closest(‘[data-action=”toggle-like”]’);
if (likeBtn) {
e.preventDefault();
toggleLike(likeBtn);
return;
}
const replyBtn = e.target.closest(‘[data-action=”toggle-reply”]’);
if (replyBtn) {
e.preventDefault();
openReplyBox(widget, Number(replyBtn.dataset.commentId || 0));
return;
}
const cancelReplyBtn = e.target.closest(‘[data-action=”cancel-reply”]’);
if (cancelReplyBtn) {
e.preventDefault();
closeReplyBox(cancelReplyBtn.closest(‘[data-role=”reply-box”]’));
}
});
widget.addEventListener(‘submit’, function (e) {
const replyForm = e.target.closest(‘.ev-comments__reply-form’);
if (replyForm) {
e.preventDefault();
submitReply(replyForm);
}
});
loadComments(true);
}
document.addEventListener(‘DOMContentLoaded’, function () {
document.querySelectorAll(‘.ev-comments’).forEach(initCommentsWidget);
});
})();
Trending
More years, more illness: Why healthy ageing is becoming a global challengeHealth
|Charity Kilei
|3 hours ago
Sudan says 75 per cent of its health facilities resume operationsSudan
|XINHUA
|15 hours ago
Lawyer moves to High Court to challenges LSK’s indefinite boycott of court proceedingsNews
|Carolyne Kubwa
|4 hours ago
Somalia opposition calls for transitional council, urges international backing amid political crisisSomalia
|Abdirahman Khalif
|11 hours ago

Rain, strong winds and cool weather expected over the next 24 hours – WeathermanNews
|Lucy Mumbi
|12 hours ago
𝐄𝐚𝐬𝐭𝐥𝐞𝐢𝐠𝐡 𝐕𝐨𝐢𝐜𝐞 𝐚𝐭 𝐍𝐢𝐧𝐞 – Religious, cultural leaders warn politicians against dividing KenyansVideos
|Zawadi Charity
|2 hours ago
OPINION: We must reject the dangerous politics of dehumanisationOpinion
|Amina Wako
|1 day ago
Can newly discovered soil fungus stop devastating African armyworm when chemicals have failed?Africa
|The Conversation
|54 minutes ago
Judge urges defence to consider plea bargain in State House guard murder trialNews
|Carolyne Kubwa
|10 hours ago
Prof John Okumu appointed substantive Kenyatta University Vice ChancellorEducation
|Lucy Mumbi
|11 hours ago


