D&D armor class calculator
Studded leather with 16 Dexterity and a shield gives AC 17: a base of 12, plus 3 from Dexterity, plus 2 for the shield. Light, medium and heavy armor each get their own Dexterity rule. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Armor
- Studded leather
- Dexterity
- 16
- Armor label
- Studded leather
- Category
- Light
- Base ac
- 12
- Dex modifier
- 3
Fifth-edition Dungeons & Dragons armor class is assembled from four parts that players constantly rearrange: a base from the armor worn (or ten if unarmored), the Dexterity modifier allowed by that armor's category, an optional shield bonus, and every other bonus from fighting styles, spells, cover, or magic items. Light armor adds the full Dexterity modifier. Medium armor usually caps that modifier at plus two. Heavy armor ignores Dexterity entirely.
How the fifth-edition armor class formula works
In Dungeons & Dragons fifth edition, armor class is not a single printed cell on the character sheet. It is a short formula whose Dexterity term changes with the armor category in the Player's Handbook. Unarmored creatures start at a base of ten and add their full Dexterity modifier.
The mage armor spell replaces that ten with thirteen and still adds the full modifier. Light armors—padded, leather, and studded leather—use bases of eleven, eleven, and twelve and also add the full Dexterity modifier, including a negative modifier when Dexterity is below ten. Medium armors—hide, chain shirt, scale mail, breastplate, and half plate—use bases from twelve through fifteen and add Dexterity only up to a cap of plus two, unless a feature such as Medium Armor Master raises that cap to three.
Heavy armors—ring mail, chain mail, splint, and plate—use bases from fourteen through eighteen and add no Dexterity at all, even when the modifier is negative. A shield normally adds two. Unarmored Defense, the monk's Wisdom or the barbarian's Constitution, adds a second ability modifier on top of the unarmored base.
Other bonuses—Defense fighting style, half or three-quarters cover, the shield of faith spell, or a magic plus-one—stack as integers after the Dexterity term.
What you can do with it
Session-zero party checks
Verify every PC's AC against the same Player's Handbook bases and Dexterity rules before the first combat.
FAQ
How is D&D 5e armor class calculated?
Armor class is base AC from the armor (or 10 if unarmored) plus the Dexterity modifier allowed by the category, plus a shield bonus (usually +2), plus Unarmored Defense and any other bonuses. Light armor adds full Dexterity; medium usually caps Dexterity at +2; heavy adds no Dexterity.
What Dexterity cap does medium armor use?
The Player's Handbook cap is +2. Light armor and unarmored add the full modifier.
What is my AC in studded leather with 16 Dexterity and a shield?
Your armor class is 17. Studded leather has a base of 12, a Dexterity of 16 gives a +3 modifier that light armor adds in full, and a shield adds 2.
Does heavy armor add my Dexterity modifier?
No. Ring mail, chain mail, splint and plate use bases from 14 to 18 and add no Dexterity at all, not even when your modifier is negative.
How does mage armor change my armor class?
Mage armor replaces the unarmored base of 10 with 13 and still adds your full Dexterity modifier. Add a shield or other bonuses on top if your character has them.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/hobby/dnd-armor-class \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"armor":"studded_leather","dexterity":16}'const res = await fetch("https://api.kit.forhosting.com/hobby/dnd-armor-class", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"armor": "studded_leather",
"dexterity": 16
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/hobby/dnd-armor-class",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"armor": "studded_leather",
"dexterity": 16
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/hobby/dnd-armor-class", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"armor":"studded_leather","dexterity":16}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"armor":"studded_leather","dexterity":16}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/hobby/dnd-armor-class", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"armor": "studded_leather",
"dexterity": 16
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "hobby.dnd_armor_class",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Failed validation is not billed; a successful call uses the published $0.002 rate.
How the fifth-edition armor class formula works
This capability hard-codes those Player's Handbook bases and category caps, applies an optional dex_cap override, and never invents a fractional armor class. If you name an unknown armor or omit base_ac on a custom suit, the request fails with invalid_input instead of guessing a number that your table never agreed to.
Input contract, response shape, and error behaviour
Pair the response with your own inventory UI. POST a JSON body with two required fields: armor, a closed list of fifth-edition names plus mage_armor, unarmored, and custom; and dexterity, an integer ability score from one to thirty from which the modifier is the floor of the score minus ten, divided by two. Optional fields refine the sum. base_ac overrides the table or is required when armor is custom, in the range zero to forty. category may be unarmored, light, medium, or heavy and overrides the default Dexterity rule when you are homebrewing a suit. dex_cap is an integer from zero to ten: zero means add no Dexterity, and a positive value is the maximum Dexterity that may be added—use three for Medium Armor Master. shield is a boolean that defaults to false; when true, shield_bonus defaults to two and may be set from zero to ten for a magic shield. unarmored_modifier is an integer from minus ten to ten for Wisdom or Constitution under Unarmored Defense. other_bonus is an integer from minus twenty to twenty for everything else. Missing armor or dexterity, a score outside one to thirty, custom armor without base_ac, and non-integers fail with invalid_input and are not billed. On success the body echoes the resolved armor, armor_label, category, base_ac, dexterity, dex_modifier, dex_applied, and dex_rule (full, capped, or none); includes dex_cap only when the rule is capped; and returns shield, shield_bonus, unarmored_modifier, other_bonus, the integer armor_class, and a formula string such as seventeen equals twelve from studded leather plus three Dexterity plus two from a shield. This endpoint computes armor class only and does not apply stealth disadvantage, Strength requirements, or spellcasting restrictions from wearing armor.
Where a D&D armor class calculator earns its keep
Character builders and virtual-tabletop companion apps need a tiny oracle that recomputes armor class whenever a player swaps leather for a breastplate, picks up a shield, or raises Dexterity from fourteen to sixteen and expects the medium-armor cap to keep the Dexterity term at plus two instead of plus three. Session-zero helpers and party-balance sheets compare six player characters against the same Player's Handbook rules so nobody reports plate plus a plus-four Dexterity modifier as twenty-two. Failed validation does not consume balance. Discord bots and spreadsheet scripts can POST armor and dexterity from a message and reply with armor_class and formula without embedding the armor table in every bot. Encounter builders for dungeon masters can price monster-like custom bases, such as natural armor thirteen plus Dexterity, by sending armor custom with a base_ac. Keep requests small, pin armor_class and the formula string in tests, and you get reproducible fifth-edition armor class totals for builders, blogs, and edge workers without standing up a full rules engine of your own.
Integration use cases
Character builder drafts
Recalculate armor_class whenever a player swaps a named 5e armor, picks up a shield, or changes Dexterity under a medium-armor cap.
Bots and virtual tabletops
Let a Discord command or VTT script POST armor and dexterity and return formula plus armor_class without embedding the PHB table.
Technical questions
Does this include Unarmored Defense, mage armor, or a shield?
Yes. Use armor unarmored with unarmored_modifier set to your Wisdom or Constitution modifier for monk or barbarian Unarmored Defense. armor mage_armor uses base 13 plus Dexterity. Set shield true to add +2, or set shield_bonus for a magic shield.
Which armors are in the table, and how do I send a custom base?
Padded, leather, studded leather, hide, chain shirt, scale mail, breastplate, half plate, ring mail, chain mail, splint, plate, plus unarmored and mage_armor. For anything else send armor custom and a base_ac, and optionally category or dex_cap to set the Dexterity rule.
What does the D&D armor class calculator cost to call?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.