D&D spell attack bonus calculator
A spell attack roll needs one number from your character sheet: the spell attack bonus.
Run — free
This calculator finds it by adding your proficiency bonus to the modifier for your class's spellcasting ability. Enter those two integers and it returns the total, the original values, and a signed formula you can check at a glance. It is useful when creating a character, updating a sheet after a level increase, preparing a monster or nonplayer character, or confirming that an automated sheet applied the standard rule correctly.
Find the two values on the character sheet
Start with the character's proficiency bonus. This is the level-based bonus shown on a standard character sheet; it is not the proficiency bonus for a particular skill, weapon, or saving throw. Next, identify the ability the class or feature uses for spellcasting. A wizard normally uses Intelligence, a cleric normally uses Wisdom, and a bard normally uses Charisma, but a specific feature can state a different ability. Use that ability's modifier, not its raw score. For example, an Intelligence score of 18 normally has a +4 modifier, so the value entered here is 4 rather than 18. Multiclass characters may have more than one spellcasting ability, so calculate the bonus separately for spells gained from each class when their abilities differ. The calculator deliberately asks for the finished proficiency bonus and ability modifier instead of character level and ability score. That keeps the rule transparent and lets it work with class features, creatures, optional rules, and homebrew values without silently assuming a particular progression table.
Add proficiency and the spellcasting modifier
The standard calculation is spell attack bonus = proficiency bonus + spellcasting ability modifier. If proficiency is +3 and the relevant ability modifier is +4, the result is +7. Write that +7 after the d20 result when a spell instructs you to make a spell attack. The returned formula keeps signs visible so negative modifiers remain unambiguous: proficiency +2 combined with an ability modifier of -1 produces +1. No die roll is performed here, and the spell's damage dice do not affect this number. A magic item, class feature, feat, condition, or other rule may grant an additional modifier to a particular attack. Those situational adjustments are outside the two-part base calculation and should be applied separately when the relevant rule says they apply. Likewise, advantage and disadvantage change how the d20 is rolled; they do not change the numeric spell attack bonus. Keeping the base value separate makes it easier to audit the sheet and then layer temporary effects onto the actual roll at the table.
Use the result for spell attacks, not saving throws
Apply this result only when the spell or feature calls for a spell attack roll, whether it is described as a melee spell attack or a ranged spell attack. Roll a d20, add the calculated spell attack bonus, and compare the total with the target's Armor Class under the applicable game rules. Do not use this number when a target makes a saving throw. A spell save Difficulty Class uses a related but different formula that normally includes a base of 8 in addition to proficiency and the spellcasting ability modifier. Also distinguish a spell attack from a weapon attack made as part of a spell: the feature's exact wording determines which attack bonus applies. Recalculate after a proficiency increase or whenever the relevant ability modifier changes. Because the calculator returns both components beside the total, you can quickly see which value needs updating. It does not choose a class, interpret a feature, add equipment bonuses, or resolve edition-specific exceptions; the governing rule text and your table's chosen rules remain the authority for those decisions.
What you can do with it
Check a new character sheet
Confirm the spell attack bonus after choosing the class's spellcasting ability and recording the character's proficiency bonus.
Update after gaining a level
Recalculate when a level increase changes proficiency or an ability score improvement changes the spellcasting modifier.
Audit a multiclass caster
Calculate separate attack bonuses for spells from classes that use different spellcasting abilities.
FAQ
What is the spell attack bonus formula?
Add the character's proficiency bonus and the modifier for the ability used to cast that spell.
Do I enter the ability score or the ability modifier?
Enter the modifier. For example, if the relevant score gives a +4 modifier, enter 4, not the raw score.
Is spell attack bonus the same as spell save DC?
No. This calculator handles spell attacks. A spell save DC normally uses a different formula that also includes a base value of 8.
Does it include bonuses from magic items or features?
No. It computes the base sum of proficiency and spellcasting ability modifier. Apply other bonuses separately when their rules say they apply.
What does the calculator cost?
It runs free in the browser on this page. Each API request costs $0.002.
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-spell-attack-bonus \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"proficiency_bonus":3,"spellcasting_ability_modifier":4}'const res = await fetch("https://api.kit.forhosting.com/hobby/dnd-spell-attack-bonus", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"proficiency_bonus": 3,
"spellcasting_ability_modifier": 4
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/hobby/dnd-spell-attack-bonus",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"proficiency_bonus": 3,
"spellcasting_ability_modifier": 4
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/hobby/dnd-spell-attack-bonus", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"proficiency_bonus":3,"spellcasting_ability_modifier":4}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"proficiency_bonus":3,"spellcasting_ability_modifier":4}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/hobby/dnd-spell-attack-bonus", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"proficiency_bonus": 3,
"spellcasting_ability_modifier": 4
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "hobby.dnd_spell_attack_bonus",
"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. |