Odsonne Edouard’s opener two minutes into the second half looked like earning the visitors victory against their wasteful hosts.
But substitute Jhon Duran’s stunning leveller brought Villa level three minutes from the end of the 90 to set up an action-packed finale.
A controversial Douglas Luiz penalty then saw Unai Emery’s men go ahead before Leon Bailey added a third late on.
Villa have now equalled their best run of top flight home wins since the 1989-90 season but for much of the afternoon they looked set for a frustrating defeat after missing a host of first half chances.
Edouard’s goal early in the second half came against the run of play but Palace also had plenty of chances in the second half, with two saves from Emi Martinez to deny Eberechi Eze proving particularly pivotal as the late drama played out.
Duran’s leveller was stunning but the immediate post-match focus will fall on referee Darren England’s award of the penalty which saw Villa go ahead. Defender Chris Richards appeared to get a big chunk of the ball when he challenged Ollie Watkins but though England was sent to the monitor by VAR Robert Jones, he stuck with his original decision after a near five-minute delay.
Over the balance of the whole game, 17 minutes of stoppage time included, Villa were probably worthy winners. But they could hardly have made harder work of it.
The big pre-match news concerned Palace boss Roy Hodgson, who missed the match after being taken unwell at the team hotel on Saturday morning.
On the pitch the visitors were without defender Marc Guehi and midfielder Michael Olise, while for Villa the full debut of Nicolo Zaniolo was the most notable aspect of the starting XI.
The hosts were bossing possession in the early stages without creating a chance before visiting defender Joel Ward laid one on a plate for Watkins. His backpass sent the striker clean through on goal but the finish, frustratingly, was rather telegraphed as Johnstone made the save. A Matty Cash cross then clattered off Richards and into the side netting as Villa looked to raise the tempo.
With 11 minutes of the half remaining, Villa thought they had taken the lead with a goal of great skill from Moussa Diaby. The record signing did superbly to bring down Pau Torres’ lofted pass with his left foot and then finish past Johnstone with his right but a subsequent VAR check revealed he had strayed just the wrong side of the last defender.
Palace survived again soon after when Cash drove a low cross through the box and Watkins failed to gamble. Cash was then guilty of a horrible air shot after Zaniolo had wriggled away from his man and pulled the ball back to the full-back 12 yards from goal.
The visitors, who lost former Villa forward Jordan Ayew to a injury midway through the opening half, had barely threatened but three minutes into the second half had the lead.
Jean-Philippe Mateta, who had replaced Ayew off the bench, outmuscled Torres on Villa’s left and delivered a cross which an unmarked Edouard fired first time past Martinez.
It was the first time Villa had trailed at home since February and things nearly got worse within a minute when Edouard got past Ezri Konsa. This time it was Torres who came to the rescue by blocking the shot.
Villa saw appeals for a penalty waved away after Watkins, Doucoure and Ward and all ended up on the floor, with the two Palace players appearing to tackle each other.
Palace were very much in the game now and Villa were grateful to alert goalkeeping from Martinez, who came out to smother at the feet of Eze after the wideman had beaten Cash to a bouncing ball.
Emery went on the offensive bringing Leon Bailey and Duran off the bench and latter tested Johnstone with a low drive.
Increasingly, you wondered whether it just wasn’t going to be Villa’s day. Watkins and Bailey both had shots blocked in quick succession before the latter curled an effort which hit the post and rebounded off the back of Johnstone’s head and behind for a corner.
Martinez denied Eze one-on-one again as the match entered the final 10 minutes and that looked even more crucial when Duran produced his moment of magic.
Chesting down Digne’s cross, he lashed a left-footed volley high into the roof of the net, giving Johnstone no chance.
The drama was far from over. Three minutes into stoppage time Watkins went down under the challenge of Richards and referee England pointed to the spot. Five minutes later, after a lengthy VAR check which saw the referee go to the monitor but stick with his decision, Luiz sent Johnstone the wrong way from the spot.
There was still plenty of stoppage time to play but Villa’s nerves were quickly eased when Bailey made it three, firing home at the far post after being picked out by Diaby.
34 VAR Moussa Diaby thinks he has broken the deadlock for Villa but a VAR check rules him to have been just offside.
47 GOAL Palace lead against the run of play. Jean-Philippe Mateta outmuscles Pau Torres and crosses for Odsonne Edouard to fire home.
87 GOAL Jhon Duran blasts home a leveller, chesting down Lucas Digne’s cross and sending an unstoppable drive beyond Sam Johnstone.
90+8 GOAL Douglas Luiz converts from the spot, following a five minute VAR check, after Chris Richards brings down Ollie Watkins in the box.
90+11 GOAL Leon Bailey seals it for Villa, firing home after being picked out by Diaby,
Villa (4-4-2): Martinez, Cash, Konsa, Torres, Digne, Zaniolo (Bailey 57), Kamara (Tielemans 57), Luiz, McGinn (Duran 71), Diaby, Watkins Subs not used: Moreno, Chambers, Lenglet, Dendoncker, Olsen (gk), Marschall (gk).
Palace (4-2-3-1): Johnstone, Ward, Richards, Andersen, Mitchell, Hughes, Doucoure, Ayew (Mateta 24), Eze, Schlupp, Edouard (Ahamada 90) Subs not used: Holding, Clyne, Ebiowei, Riedewald, Rak-Sakyi, Henderson (gk), Matthews (gk).