D&D 5e Spell Slot Calculator
ANA›Life Services Authority›National Calculator Authority›D&D 5e Spell Slot Calculator
.calc-container { max-width: 640px; margin: 2rem 0; padding: 1.5rem; background: #fff; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); font-family: system-ui, -apple-system, sans-serif; } .calc-container h3 { font-family: Georgia, serif; font-size: 1.15rem; color: #1a1a1a; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 2px solid var(--ac, #3d5a80); } .calc-row { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem; flex-wrap: wrap; } .calc-row label { min-width: 160px; font-size: 0.9rem; color: #333; font-weight: 500; } .calc-row input[type="number"], .calc-row select { flex: 1; min-width: 120px; max-width: 200px; padding: 0.5rem 0.6rem; border: 1px solid #ccc; border-radius: 4px; font-size: 0.9rem; font-family: system-ui, sans-serif; color: #1a1a1a; background: #fafaf8; } .calc-row input:focus, .calc-row select:focus { outline: none; border-color: var(--ac, #3d5a80); box-shadow: 0 0 0 2px rgba(26,74,138,0.12); } .calc-row .unit { font-size: 0.82rem; color: #888; min-width: 30px; } .calc-btn { display: inline-block; margin-top: 0.5rem; padding: 0.55rem 1.5rem; background: var(--ac, #3d5a80); color: #fff; border: none; border-radius: 4px; font-size: 0.9rem; font-weight: 600; cursor: pointer; font-family: system-ui, sans-serif; } .calc-btn:hover { opacity: 0.9; } .calc-result { margin-top: 1.25rem; padding: 1rem 1.25rem; background: #f0f6fc; border-left: 3px solid var(--ac, #3d5a80); border-radius: 0 6px 6px 0; display: none; } .calc-result.visible { display: block; } .calc-result-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; color: #666; margin-bottom: 0.25rem; } .calc-result-value { font-size: 1.6rem; font-weight: 700; color: var(--ac, #3d5a80); } .calc-result-detail { font-size: 0.85rem; color: #555; margin-top: 0.5rem; line-height: 1.5; } .calc-note { margin-top: 1rem; font-size: 0.8rem; color: #888; font-style: italic; } .calc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin-top: 0.75rem; } .calc-grid-item { padding: 0.6rem 0.8rem; background: #f8f9fa; border-radius: 4px; border: 1px solid #eee; } .calc-grid-item .label { font-size: 0.75rem; color: #888; text-transform: uppercase; letter-spacing: 0.04em; } .calc-grid-item .value { font-size: 1.1rem; font-weight: 600; color: #1a1a1a; } @media (max-width: 720px) { .calc-row { flex-direction: column; align-items: flex-start; gap: 0.3rem; } .calc-row label { min-width: auto; } .calc-row input[type="number"], .calc-row select { max-width: 100%; width: 100%; } .calc-grid { grid-template-columns: 1fr; } } .calc-chart { margin: 1rem 0; text-align: center; } .calc-chart svg { max-width: 100%; height: auto; } .calc-chart-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem 1.2rem; margin-top: 0.6rem; font-size: 0.8rem; color: #555; } .calc-chart-legend span { display: inline-flex; align-items: center; gap: 0.3rem; } .calc-chart-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; font-style: normal; } .calc-related { max-width: 640px; margin: 2rem 0 1rem; padding: 1.25rem 1.5rem; background: #f8f9fa; border: 1px solid #e8e8e8; border-radius: 8px; } .calc-related h3 { font-family: Georgia, serif; font-size: 1rem; color: #1a1a1a; margin: 0 0 0.75rem; padding-bottom: 0.4rem; border-bottom: 2px solid var(--ac, #3d5a80); } .calc-related-list { list-style: none; padding: 0; margin: 0 0 0.75rem; display: grid; grid-template-columns: 1fr 1fr; gap: 0.4rem 1.5rem; } .calc-related-list li a { font-size: 0.88rem; color: var(--ac, #3d5a80); text-decoration: none; } .calc-related-list li a:hover { text-decoration: underline; } .calc-browse-all { margin: 0.5rem 0 0; font-size: 0.9rem; font-weight: 600; } .calc-browse-all a { color: var(--ac, #3d5a80); text-decoration: none; } .calc-browse-all a:hover { text-decoration: underline; } @media (max-width: 720px) { .calc-related-list { grid-template-columns: 1fr; } }
D&D 5e Spell Slot Calculator
Calculate your available spell slots based on your class and character level using official D&D 5e rules.
Spellcasting Class
Wizard Sorcerer Cleric Druid Bard
Paladin Ranger
Fighter (Eldritch Knight) Rogue (Arcane Trickster)
Warlock
Class Level (1–20)
Include Multiclass? (Optional)
No Multiclass + Wizard + Sorcerer + Cleric + Druid + Bard + Paladin + Ranger + Eldritch Knight + Arcane Trickster
Multiclass Level (1–20)
Calculate Spell Slots Enter your class and level, then click Calculate.
(function() {
// ── Spell Slot Tables (PHB p.165) ────────────────────────────────────────── // Full caster: indexed by caster level 1–20, values = [1st,2nd,3rd,4th,5th,6th,7th,8th,9th] const FULL_CASTER_SLOTS = [ [2,0,0,0,0,0,0,0,0], // 1 [3,0,0,0,0,0,0,0,0], // 2 [4,2,0,0,0,0,0,0,0], // 3 [4,3,0,0,0,0,0,0,0], // 4 [4,3,2,0,0,0,0,0,0], // 5 [4,3,3,0,0,0,0,0,0], // 6 [4,3,3,1,0,0,0,0,0], // 7 [4,3,3,2,0,0,0,0,0], // 8 [4,3,3,3,1,0,0,0,0], // 9 [4,3,3,3,2,0,0,0,0], // 10 [4,3,3,3,2,1,0,0,0], // 11 [4,3,3,3,2,1,0,0,0], // 12 [4,3,3,3,2,1,1,0,0], // 13 [4,3,3,3,2,1,1,0,0], // 14 [4,3,3,3,2,1,1,1,0], // 15 [4,3,3,3,2,1,1,1,0], // 16 [4,3,3,3,2,1,1,1,1], // 17 [4,3,3,3,3,1,1,1,1], // 18 [4,3,3,3,3,2,1,1,1], // 19 [4,3,3,3,3,2,2,1,1], // 20 ];
// Half caster: indexed by class level 1–20 (levels 1 get no slots) const HALF_CASTER_SLOTS = [ [0,0,0,0,0,0,0,0,0], // 1 [2,0,0,0,0,0,0,0,0], // 2 [3,0,0,0,0,0,0,0,0], // 3 [3,0,0,0,0,0,0,0,0], // 4 [4,2,0,0,0,0,0,0,0], // 5 [4,2,0,0,0,0,0,0,0], // 6 [4,3,0,0,0,0,0,0,0], // 7 [4,3,0,0,0,0,0,0,0], // 8 [4,3,2,0,0,0,0,0,0], // 9 [4,3,2,0,0,0,0,0,0], // 10 [4,3,3,0,0,0,0,0,0], // 11 [4,3,3,0,0,0,0,0,0], // 12 [4,3,3,1,0,0,0,0,0], // 13 [4,3,3,1,0,0,0,0,0], // 14 [4,3,3,2,0,0,0,0,0], // 15 [4,3,3,2,0,0,0,0,0], // 16 [4,3,3,3,1,0,0,0,0], // 17 [4,3,3,3,1,0,0,0,0], // 18 [4,3,3,3,2,0,0,0,0], // 19 [4,3,3,3,2,0,0,0,0], // 20 ];
// Third caster: indexed by class level 1–20 const THIRD_CASTER_SLOTS = [ [0,0,0,0,0,0,0,0,0], // 1 [0,0,0,0,0,0,0,0,0], // 2 [2,0,0,0,0,0,0,0,0], // 3 [3,0,0,0,0,0,0,0,0], // 4 [3,0,0,0,0,0,0,0,0], // 5 [3,0,0,0,0,0,0,0,0], // 6 [4,2,0,0,0,0,0,0,0], // 7 [4,2,0,0,0,0,0,0,0], // 8 [4,2,0,0,0,0,0,0,0], // 9 [4,3,0,0,0,0,0,0,0], // 10 [4,3,0,0,0,0,0,0,0], // 11 [4,3,0,0,0,0,0,0,0], // 12 [4,3,2,0,0,0,0,0,0], // 13 [4,3,2,0,0,0,0,0,0], // 14 [4,3,2,0,0,0,0,0,0], // 15 [4,3,3,0,0,0,0,0,0], // 16 [4,3,3,0,0,0,0,0,0], // 17 [4,3,3,0,0,0,0,0,0], // 18 [4,3,3,1,0,0,0,0,0], // 19 [4,3,3,1,0,0,0,0,0], // 20 ];
// Warlock Pact Magic: [slots, slot_level] indexed by class level 1–20 const WARLOCK_PACT = [ [1,1],[2,1],[2,2],[2,2],[2,3], [2,3],[2,4],[2,4],[2,5],[2,5], [3,5],[3,5],[3,5],[3,5],[3,5], [3,5],[4,5],[4,5],[4,5],[4,5] ];
// Multiclass spell slot table (PHB p.165) // Indexed by total caster level 1–20 const MULTICLASS_SLOTS = FULL_CASTER_SLOTS; // same table
function getCasterType(cls) { if (['wizard','sorcerer','cleric','druid','bard'].includes(cls)) return 'full'; if (['paladin','ranger'].includes(cls)) return 'half'; if (['eldritch_knight','arcane_trickster'].includes(cls)) return 'third'; if (cls === 'warlock') return 'warlock'; return 'none'; }
function getCasterLevel(cls, classLevel) { const type = getCasterType(cls); if (type === 'full') return classLevel; if (type === 'half') return Math.floor(classLevel / 2); if (type === 'third') return Math.floor(classLevel / 3); return 0; // warlock handled separately }
function getSlots(cls, level) { const type = getCasterType(cls); if (type === 'full') return FULL_CASTER_SLOTS[level - 1].slice(); if (type === 'half') return HALF_CASTER_SLOTS[level - 1].slice(); if (type === 'third') return THIRD_CASTER_SLOTS[level - 1].slice(); return null; }
function getSpellsKnownOrPrepared(cls, level) {
const notes = {
wizard: Spells in Spellbook: Starts with 6 + INT modifier; gains 2 per level. Prepared: INT modifier + Wizard level (min 1).,
sorcerer: Spells Known: Fixed by level (2 at 1st, up to 15 at 20th). No preparation needed.,
cleric: Prepared: WIS modifier + Cleric level (min 1). Access to entire Cleric spell list.,
druid: Prepared: WIS modifier + Druid level (min 1). Access to entire Druid spell list.,
bard: Spells Known: Fixed by level (4 at 1st, up to 22 at 20th). No preparation needed.,
paladin: Prepared: CHA modifier + half Paladin level (min 1). Access to entire Paladin spell list.,
ranger: Spells Known: Fixed by level (2 at 2nd, up to 11 at 20th). No preparation needed.,
eldritch_knight: Spells Known: Fixed by level (3 at 3rd, up to 13 at 20th). Mostly Abjuration & Evocation.,
arcane_trickster: Spells Known: Fixed by level (3 at 3rd, up to 13 at 20th). Mostly Enchantment & Illusion.,
warlock: Spells Known: Fixed by level (2 at 1st, up to 15 at 20th). All slots are Pact Magic slots.,
};
return notes[cls] || '';
}
window.dndUpdateSubclass = function() { const cls = document.getElementById('d-d-class').value; const mcGroup = document.getElementById('d-d-multiclass-level-group'); const mc = document.getElementById('d-d-multiclass').value; mcGroup.style.display = (mc !== 'none') ? 'block' : 'none'; };
document.getElementById('d-d-multiclass').addEventListener('change', function() { const mcGroup = document.getElementById('d-d-multiclass-level-group'); mcGroup.style.display = (this.value !== 'none') ? 'block' : 'none'; });
window.dndCalc = function() { const resultEl = document.getElementById('d-d-result'); const cls = document.getElementById('d-d-class').value; const levelRaw = parseInt(document.getElementById('d-d-level').value); const mc = document.getElementById('d-d-multiclass').value; const mcLevelRaw = parseInt(document.getElementById('d-d-multiclass-level').value) || 0;
// ── Validation ──────────────────────────────────────────────────────────── if (isNaN(levelRaw) || levelRaw 20) { resultEl.innerHTML = '⚠ Class level must be between 1 and 20.'; return; } if (mc !== 'none' && (isNaN(mcLevelRaw) || mcLevelRaw 20)) { resultEl.innerHTML = '⚠ Multiclass level must be between 1 and 20.'; return; } if (mc !== 'none' && mc === cls) { resultEl.innerHTML = '⚠ Multiclass cannot be the same as your primary class.'; return; } if (mc !== 'none' && levelRaw + mcLevelRaw > 20) { resultEl.innerHTML = '⚠ Total character level cannot exceed 20.'; return; }
const classNames = { wizard:'Wizard', sorcerer:'Sorcerer', cleric:'Cleric', druid:'Druid', bard:'Bard', paladin:'Paladin', ranger:'Ranger', eldritch_knight:'Eldritch Knight', arcane_trickster:'Arcane Trickster', warlock:'Warlock' };
let html = '';
// ── Warlock (Pact Magic) ──────────────────────────────────────────────────
if (cls === 'warlock' && mc === 'none') {
const [numSlots, slotLevel] = WARLOCK_PACT[levelRaw - 1];
const ordinals = ['','1st','2nd','3rd','4th','5th'];
html += ### Warlock — Level ${levelRaw};
html += `Pact Magic Slots: ${numSlots} slot${numSlots > 1 ? 's' : ''} at ${ordinals[slotLevel]} level
;
html +=Pact Magic slots are regained on a Short or Long Rest.
;
html +=${getSpellsKnownOrPrepared(cls, levelRaw)}
`; resultEl.innerHTML = html; return; }
// ── Single Class (non-Warlock) ────────────────────────────────────────────
if (mc === 'none') {
const slots = getSlots(cls, levelRaw);
const ordinals = ['1st','2nd','3rd','4th','5th','6th','7th','8th','9th'];
html += ### ${classNames[cls]} — Level ${levelRaw};
html += ;
html +=;
ordinals.forEach(o => { html += ${o}; });
html += ;
slots.forEach(s => {
const bg = s > 0 ? '#eaf4fb' : '#f5f5f5';
const fw = s > 0 ? 'bold' : 'normal';
const color = s > 0 ? '#2c3e50' : '#bbb';
html += `${s > 0 ? s : '—'}`;
});
html +=;
const totalSlots = slots.reduce((a,b) => a+b, 0);
html += `Total Spell Slots: ${totalSlots}
;
html +=All spell slots are regained on a Long Rest.
;
html +=${getSpellsKnownOrPrepared(cls, levelRaw)}
`; resultEl.innerHTML = html; return; }
// ── Multiclass ──────────────────────────────────────────────────────────── // Warlock multiclass: Pact Magic slots are separate; other slots use multiclass table let warlockSlots = null; let warlockLevel = 0; let primaryCasterLevel = 0; let mcCasterLevel = 0;
if (cls === 'warlock') { warlockLevel = levelRaw; warlockSlots = WARLOCK_PACT[levelRaw - 1]; mcCasterLevel = getCasterLevel(mc, mcLevelRaw); primaryCasterLevel = 0; // warlock doesn't contribute to multiclass table } else if (mc === 'warlock') { warlockLevel = mcLevelRaw; warlockSlots = WARLOCK_PACT[mcLevelRaw - 1]; primaryCasterLevel = getCasterLevel(cls, levelRaw); mcCasterLevel = 0; } else { primaryCasterLevel = getCasterLevel(cls, levelRaw); mcCasterLevel = getCasterLevel(mc, mcLevelRaw); }
const totalCasterLevel = primaryCasterLevel + mcCasterLevel; const ordinals = ['1st','2nd','3rd','4th','5th','6th','7th','8th','9th'];
html += ### Multiclass: ${classNames[cls]} ${levelRaw} / ${classNames[mc]} ${mcLevelRaw};
// Multiclass spell slots if (totalCasterLevel > 0) { const clampedLevel = Math.min(Math.max(totalCasterLevel, 1), 20); const mcSlots = MULTICLASS_SLOTS[clampedLevel - 1]; html += `Combined Caster Level: ${clampedLevel}
;
html += ``;
html += ``;
ordinals.forEach(o => { html +=${o}; });
html += ``;
mcSlots.forEach(s => {
const bg = s > 0 ? '#eaf4fb' : '#f5f5f5';
const fw = s > 0 ? 'bold' : 'normal';
const color = s > 0 ? '#2c3e50' : '#bbb';
html +=${s > 0 ? s : '—'};
});
html += ``;
const totalSlots = mcSlots.reduce((a,b) => a+b, 0);
html +=Total Spell Slots: ${totalSlots} (regained on Long Rest)
;
} else {
html +=No combined spell slots (neither class contributes to the multiclass table at these levels).
`; }
// Warlock Pact Magic (separate) if (warlockSlots) { const [numSlots, slotLevel] = warlockSlots; const ordinalNames = ['','1st','2nd','3rd','4th','5th']; html += `Pact Magic Slots (Warlock ${warlockLevel}): ${numSlots} slot${numSlots>1?'s':''} at ${ordinalNames[slotLevel]} level — regained on Short or Long Rest.
;
html +=Pact Magic slots are tracked separately from regular spell slots but can be used to cast spells from either class.
`; }
// Caster level breakdown
html += `;
html +=Caster Level Breakdown:;
if (cls !== 'warlock') {
const type = getCasterType(cls);
const divisor = type === 'full' ? 1 : type === 'half' ? 2 : 3;
html +=${classNames[cls]} ${levelRaw} → ${primaryCasterLevel} caster level${divisor>1?' (÷'+divisor+')':''};
}
if (mc !== 'warlock') {
const type = getCasterType(mc);
const divisor = type === 'full' ? 1 : type === 'half' ? 2 : 3;
html +=${classNames[mc]} ${mcLevelRaw} → ${mcCasterLevel} caster level${divisor>1?' (÷'+divisor+')':''};
}
html +=
`;
resultEl.innerHTML = html; };
})();
#### Formula
Single Class (Full Caster): Spell slots are read directly from the class table (PHB p.114–163). Full casters include Wizard, Sorcerer, Cleric, Druid, and Bard.
Half Casters (Paladin, Ranger): Effective caster level = ⌊Class Level ÷ 2⌋. Slots are read from the half-caster table.
Third Casters (Eldritch Knight, Arcane Trickster): Effective caster level = ⌊Class Level ÷ 3⌋. Slots begin at class level 3.
Warlock (Pact Magic): Uses a separate Pact Magic system. Slots are determined by Warlock level and are all of the same level. Regained on Short or Long Rest.
Multiclass Spell Slots (PHB p.165): Total Caster Level = (Full caster levels × 1) + (Half caster levels ÷ 2, rounded down) + (Third caster levels ÷ 3, rounded down). Spell slots are then read from the full caster table using the Total Caster Level. Warlock Pact Magic slots are tracked separately and added on top.
#### Assumptions & References
- All slot tables are sourced from the Player's Handbook (5th Edition), Chapter 10 and Appendix.
More Calculators
- Credit Freeze vs. Credit Monitoring Cost-Benefit Calculator
- Motor Power and Torque Calculator
- Commercial Property ROI Calculator
- 4-20mA Signal Scaling Calculator
- EV Charging Time Calculator by Battery Size and Charger Level
- Conveyor Belt Speed and Throughput Calculator
- Home Charger Installation Cost Estimator (Level 1 vs Level 2)
- New Mexico Contractor License Fee Calculator
- New Jersey Commercial Contractor License Fee Calculator
- Commercial Project Overhead and Markup Calculator
- NJ Prevailing Wage Calculator
- New Mexico Construction Project Tax Calculator
Read Next
Study Time Planner Authority Network America › Life Services Authority › National Calculator Authority .calc-container { max-width: 640px;...