If you’ve ever shipped one “hero” image to every visitor, you’ve probably over-served low‑end phones and under‑served high‑end laptops. The Device Memory API gives you a simple hint about a device’s RAM so you can tune quality without building a full capability profiler.
What it is
- navigator.deviceMemory returns an approximate, coarse number of gigabytes (typical values: 0.25, 0.5, 1, 2, 4, 8). It’s privacy‑preserving and only available in secure contexts (HTTPS or localhost).
- The value is a hint, not a benchmark. Use it to bucket users into tiers, not to gate features.
Why it helps
- Performance: Smaller downloads for constrained devices reduce time‑to‑interactive and memory pressure.
- Battery and data: Lower tiers save energy and bandwidth where it matters most.
- Progressive enhancement: High‑end devices get sharper media or richer effects.
Leading practices
- Treat the value as advisory. Combine with other signals (save‑data, network info, viewport) when making bigger decisions.
- Keep tiers coarse and deterministic to avoid layout thrash and fingerprinting concerns.
- Always ship an accessible, functional baseline. The demo defaults to a medium image when the API isn’t available.
Support and caveats
Support is good in Chromium‑based browsers; other engines may return undefined. Always code defensive paths and serve over HTTPS.
Device Memory API Demo
Device Memory API — Quick demo
Device memory: detecting…
Quality tier: —
This demo reads navigator.deviceMemory (approx. GB) and picks a content-quality tier. Must run
on HTTPS or localhost.
/* style.css */
body {
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
padding: 24px;
}
.card {
border: 1px solid #ddd;
padding: 16px;
border-radius: 8px;
max-width: 720px;
}
.status {
margin: 8px 0;
font-weight: 600;
}
img.demo {
width: 100%;
max-width: 600px;
height: auto;
border-radius: 6px;
display: block;
margin-top: 12px;
}
.note {
color: #666;
margin-top: 10px;
font-size: 0.9rem;
}
button {
margin-top: 12px;
}
// Utility: pick a tier name from the numeric RAM value (GB)
const memoryToTier = (ramValue) => {
// Common values are 0.25, 0.5, 1, 2, 4, 8 but the API is coarse and intentionally privacy-preserving.
if (ramValue === undefined || ramValue === null) return 'unknown';
// Choose thresholds (tweak to suit your app)
if (ramValue < 1) return 'low';
if (ramValue >= 1 && ramValue < 4) return 'medium';
return 'high';
};
// Set the image src depending on quality tier.
const applyQualityTier = (tier) => {
const hero = document.querySelector('#hero');
if (tier === 'low') {
// smaller image, faster to download
hero.src = 'https://picsum.photos/600/320?grayscale&random=1';
hero.alt = 'Low-quality image (grayscale, smaller)';
} else if (tier === 'medium') {
hero.src = 'https://picsum.photos/900/480?random=2';
hero.alt = 'Medium-quality image';
} else if (tier === 'high') {
// larger, high-res image
hero.src = 'https://picsum.photos/1400/700?random=3';
hero.alt = 'High-quality image';
} else {
hero.src = 'https://picsum.photos/900/480?random=99';
hero.alt = 'Default image';
}
};
// Helper function to safely update an element with a label and an emphasized value.
const updateElementWithEmphasis = (element, label, value) => {
// Clear any previous content to prevent duplicating nodes on refresh.
element.textContent = '';
// Create the element that will contain the dynamic value.
const em = document.createElement('em');
em.textContent = value;
// Append the static text label and the new element to the parent.
element.appendChild(document.createTextNode(label));
element.appendChild(em);
};
// Update UI with memory and tier info, now using secure DOM methods instead of innerHTML.
const updateUI = (memValue) => {
const memEl = document.querySelector('#device-memory');
const tierEl = document.querySelector('#tier');
const compatEl = document.querySelector('#compat-note');
if (memValue === undefined) {
updateElementWithEmphasis(memEl, 'Device memory: ', 'not available');
compatEl.textContent =
'Device Memory API not supported in this browser. See MDN for compatibility (open in a secure context).';
updateElementWithEmphasis(tierEl, 'Quality tier: ', 'fallback');
applyQualityTier('medium'); // app-level fallback
} else {
const tier = memoryToTier(memValue);
updateElementWithEmphasis(
memEl,
'Device memory: ',
`${memValue} GB (approx.)`
);
updateElementWithEmphasis(tierEl, 'Quality tier: ', tier);
compatEl.textContent =
'Value provided by navigator.deviceMemory (approximate & coarse).';
applyQualityTier(tier);
}
};
// Try to start a worker and show WorkerNavigator.deviceMemory usage
const startWorkerAndReport = (memValue) => {
if (!window.Worker) return;
try {
const w = new Worker('worker.js');
// send main-thread value to worker (worker can also read self.navigator.deviceMemory)
w.postMessage({ mainMemory: memValue });
w.onmessage = (ev) => {
// worker will send back a message with its observation
console.log('Worker says:', ev.data);
const compatEl = document.getElementById('compat-note');
compatEl.textContent += ` Worker reported deviceMemory: ${ev.data.workerMemory}`;
};
} catch (e) {
console.warn('Could not start worker:', e);
}
};
// Main detection function
const detectAndApply = () => {
// navigator.deviceMemory is the API (available in secure contexts)
// It's intentionally coarse to avoid fine-grained fingerprinting.
const mem = navigator.deviceMemory; // may be undefined
updateUI(mem);
startWorkerAndReport(mem);
};
// --- Event Listeners and Initial Run ---
// Wire up UI
document.querySelector('#refresh').addEventListener('click', detectAndApply);
// Initial run (works on https or localhost; otherwise deviceMemory likely undefined)
detectAndApply();
// Extra: show a friendly compatibility tip if not secure context
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
const compatEl = document.getElementById('compat-note');
compatEl.textContent =
'Tip: serve this page over HTTPS or run via http://localhost to allow secure-context-only APIs.';
}
Bottom line
The Device Memory API is a tiny hint that unlocks right‑sized experiences. Use it to tailor media and effects by tier, not to exclude users—your sites will feel faster on low‑end hardware and look better on powerful machines.

