The warrior Kaulder (Vin Diesel) seeks out witches with his allies, the Axe and Cross. The witch hunter is haunted by the thoughts of his dead wife Helena (Lotte Verbeek) and daughter Elizabeth (Sloane Combs). The men walk through the woods before encountering a horde of witches, which the men proceed to slay. Kaulder takes out a number of witches, but his main target is the Witch Queen (Julie Engelbrecht). Kaulder battles the Queen until she knocks him into a pit within a large tree. She takes the fight down there with Kaulder as the tree begins to catch fire. Kaulder takes his blade and sets it on fire to kill the Witch Queen with "iron and fire", ready to perish himself. However, before the Witch Queen dies, she curses Kaulder with immortality, so that he may always live with his suffering.
800 years later in the present day year of 2015, Kaulder is on a plane where he finds a young witch, Bronwyn (Bex Taylor-Klaus), who is in possession of some weather runes that Kaulder is seeking. Outside, a storm is pounding the plane until Kaulder gets his hands on the runes and calms the storm.
Kaulder continues to work in New York City with the Axe and Cross, made up of special priests called "Dolans". Kaulder's current ally is Dolan The 36th (Michael Caine), who is approaching retirement. His successor is set to be the 37th (Elijah Wood), a young man eager to work with Kaulder. 36th warns 37th of how intense Kaulder can be.
37th calls Kaulder one day to inform him that 36th has passed on. After the Axe and Cross hold their service for 36th, 37th becomes initiated as the next Dolan. He tells Kaulder that he remembers him from his childhood since Kaulder killed the witches that killed 37th's parents, and he has been waiting all his life to fight with Kaulder.
The two go to 36th's apartment to find answers. Kaulder notices three dead insects scattered close to each other and senses something suspicious. He discovers that the place has been cursed with dark magic, implying that 36th was murdered.
Kaulder brings 37th to a bakery run by Max Schlesinger (Isaach de Bankole), who uses magic creatures in his food to enchant customers. He has done shady dealings with witches and warlocks, leading them to suspect that Max gave something valuable to a warlock named Ellic (Joseph Gilgun), who was sent by someone worse to look for something in 36th's apartment. Kaulder brings Ellic before a council of witches led by Glaeser (Rena Owen) to determine Ellic's fate. He is imprisoned by them.
Kaulder and 37th go to 36th's body and realize that he's not dead, but cursed, and the only way to break the curse is to kill the witch or warlock that did it to him. Back in the apartment, Kaulder notices a book that 36th left clues in. On three separate pages, the words "remember", "your", and "death" have bloody fingerprints on them. Kaulder knows it's a message, and he states that there's only one way for him to remember his death: magic.
Kaulder goes to a witch bar run by Chloe (Rose Leslie), who is a special type of witch known as a Dreamwalker. As he enters the bar, all the other witches and warlocks head for the hills, knowing of the witch hunter's brutal reputation against their kind. Kaulder approaches Chloe and asks for a memory spell to remember his death. She injects such a spell into a cherry for Kaulder to consume. He pops the cherry in his mouth and lays back, making Chloe think he's passed out. She takes the opportunity for a witch hunter selfie, but Kaulder is still awake. He then swallows the cherry for real and sees himself walking toward the burning tree where he fought the Witch Queen. He enters and sees his charred corpse, but before anything else can be shown, a warlock named Belial (Olafur Darri Olafsson) pulls him out of the spell and has Kaulder chained to the floor. Kaulder breaks the bones in his hand to release himself as Belial lights the bar on fire. Kaulder and Chloe get out of there in time as the place is destroyed.
Chloe wakes up in an apartment and wanders through it. Dark forces begin to rip through the apartment and she briefly appears to be pulled into the walls where she sees a monstrous entity. Kaulder's arms then appear to pull Chloe out until she reawakens to the real world. She's pissed at Kaulder for causing the destruction of her bar, but he still needs a memory spell to figure out what he needs to remember from his death. Knowing that Chloe is a Dreamwalker and that she doesn't need a liquid potion to help Kaulder, he gets her to take both of them into his mind to remember the day he died. They find his charred body again, but this time, they hide as the Axe and Cross arrive. They see the Witch Queen's corpse crumble, leaving her heart still beating. The Dolan tries to stab it, but the burnt Kaulder awakens and screams in pain. Realizing that the heart can't be destroyed without killing Kaulder for good, the Dolan takes the heart with him, leading present day Kaulder to figure out that the Axe and Cross betrayed him and let him endure immortality.
Chloe receives a phone call from her friend Miranda (Aimee Carrero), whom she last saw as Kaulder arrived at the bar. The two find Miranda dead after Belial got through with her. He calls them from Miranda's phone to taunt Kaulder.
Kaulder and Chloe go to a place where witches are disguised as beautiful women with the power of magic gems that conceal their ugliness. They find the leader, Danique (Dawn Olivieri), who puts Kaulder under a trance where he sees Helena and Elizabeth. Chloe enters Kaulder's mind and breaks him out of the trance. They then interrogate Danique over her business with Belial. She confesses that he helped them obtain the gems in return for helping him obtain the heart of the Witch Queen. Before they leave, Chloe crushes Danique's gem, making her look like a hag once again.
Belial locates the Witch Queen's heart with the council of witches, all of whom he murders. He releases Ellic and takes Max to use him as a cocoon to bring the Queen back after burying the heart in the dirt next to Max. Kaulder arrives and finds Max held up by roots. Belial appears from behind but Kaulder kills him with a dagger to the throat. The Witch Queen is already half-alive until she uses a root to grab Kaulder and use his immortality (which she says was always meant for her) to fully return. She peels off Max's skin and emerges in her true form before setting off to unleash her plague upon humanity.
Kaulder returns home to find 36th, reawakened after Belial's death. Although Kaulder thinks he's failed in stopping the Witch Queen and is discouraged by the Axe and Cross's deception, 36th encourages him to do what he's always done best.
The Witch Queen uses Ellic as a vessel to unleash her plague. Kaulder and Chloe find him in a trance. Chloe enters Ellic's mind to kill him and stop the plague while Kaulder goes after the Queen. Chloe fights Ellic in his mind and pushes him down a hole where he lands on his face and dies, holding off the plague. Still, the Queen's dark magic is spreading across the city. Kaulder battles her and nearly kills her until 37th enters, holding Chloe at gunpoint. He reveals that the witches Kaulder killed in 37th's youth weren't attacking his parents, they WERE his parents. He gives Chloe to the Witch Queen in the hope that she will grant him the magic that he was born without, but the Queen refuses and kills 37th. The Queen possesses Chloe and continues to spread the plague. Kaulder resumes his fight after being motivated by a vision of Helena and Elizabeth. As the Queen uses her powers against Kaulder, he grabs his sword and hurls it into the Queen's chest, where it combines with falling lightning bolts to destroy the Queen once again. As her body crumbles, her heart is exposed again. Kaulder is ready to permanently get rid of her and himself, but Chloe stops him.
Despite retaining his immortality, Kaulder is more at peace than before, now having found a new reason to keep living. He joins Chloe as they drive trough the city on another adventure.