Spain had the better of the early exchanges, twice creating chances to open the scoring.
Mikel Oyarzabal was played through on goal by Pedri but his touch let him down, and Ferran Torres saw his shot from outside the box dribble wide.
Italy got their first opportunity of the game, and it was one that they may feel they should have done better with.
Emerson got in behind after a one-two with Lorenzo Insigne and squared for Ciro Immobile.
Goalkeeper Unai Simon was out of his goal, but neither Immobile nor Nicolo Barella could get a shot away.
The best chance of the half came shortly afterwards. Pedri and Oyarzabal were again influential, working an opening for Dani Olmo, but the RB Leipzig man’s shot was well saved by Gianluigi Donnarumma when he really ought to have scored.
Shortly before half time, Italy came close to nicking an opener. Insigne slipped the ball to Emerson out on the left, and the defender clipped the crossbar from a tight angle.
Both sides came out firing early in the second half. Oyarzabal laid off for Sergio Busquets to fire over from the edge of the box, and Federico Chiesa had a shot saved.
But Chiesa wasn’t to be denied again on the hour mark as the Azzurri hit Spain with a deadly counter attack.
Insigne tried to find Immobile with a through ball but the forward was denied by an excellent Aymeric Laporte tackle.
However, it fell straight to Chiesa, who expertly bent an effort into the far corner to give his side the lead.
Luis Enrique’s side wasted no time in trying to get back into the game. Koke floated a beautiful cross into Oyarzabal, who failed to make contact when just a touch would have probably found the net. Olmo also had a shot miss the target.
They would eventually find an equaliser with just ten minutes remaining. Substitute Alvaro Morata exchanged passes with Olmo and coolly rolled the ball into the bottom corner with his left foot.
Neither side could force a winner before the whistle, taking the game to extra time – the third time in a row that Spain have needed the additional 30 minutes.
There wasn’t much to talk about in extra time. Domenico Berardi had a goal ruled out for offside, but no one was able to stop the game from going to a penalty shootout.
Manuel Locatelli was the first to step up to the spot, and he saw his attempt saved by Simon. Olmo was next with the opportunity to put Spain in front, but he blazed over the crossbar.
Andrea Belotti was next, and he was the first to score, emphatically burying his penalty into the bottom left corner. Gerard Moreno managed to match Belotti by firing into the roof of the net.
Italy’s third taker was Leonardo Bonucci, who showed no signs of nerves by sending Simon the wrong way. Thiago Alcantara converted his effort in similar fashion, rolling into the bottom left corner.
Federico Bernardeschi stepped up and powered his penalty into the top right corner, giving the goalkeeper no chance.
Goalscorer Morata was the next to take the walk, but his weak effort was saved by Donnarumma.
Jorginho was the fifth to take for Italy, knowing that a goal would send Italy to the final. He converted in his traditional style, placing the ball into the bottom corner.
The victory secures Italy’s place in the final. They will face England or Denmark at Wembley on Sunday.
Gianluigi Donnarumma (8/10) – Made one very good save from Olmo and kept out Morata’s penalty in the shootout. Sometimes looked a bit shaky with the ball at his feet.
Giovanni Di Lorenzo (8/10) *MOTM* – Offered little going forward, but defended very well. Nullified the pace of Alba down his side.
Leonardo Bonucci (7/10) – Coped with most things thrown his way. Occasionally let off the hook by wasteful finishing from Spain.
Giorgio Chiellini (7/10) – Much like Bonucci, was often solid in the heart of defence. Good distribution, but let a little too much past him.
Emerson (7/10) – Came in for the injured Spinazzola and deputised admirably. Looked like Italy’s biggest threat in the first half.
Jorginho (7/10) – Nerves of steel for his penalty. Good on the ball and battled well. A fine evening.
Nicolo Barella (6/10) – Had a fascinating battle up against Busquets, but often came off second best.
Marco Verratti (6/10) – A few nice touches in midfield, but didn’t control the game and sometimes struggled against Spain’s midfield trio.
Federico Chiesa (7/10) – Scored a beauty to break the deadlock. Caused some problems in the Spanish backline.
Ciro Immobile (6/10) – Linked up well but didn’t pose enough of a goal threat. Substituted on 60 minutes.
Lorenzo Insigne (6/10) – Some good link up play with Emerson down the left and played a lovely through ball for Chiesa’s goal, but didn’t make enough of an impact.
Domenico Berardi (7/10)
Matteo Pessina (6/10)
Rafael Toloi (6/10)
Manuel Locatelli (5/10)
Andrea Belotti (6/10)
Federico Bernardeschi (NA/10)
Unai Simon (7/10) – Nothing he could do about Chiesa’s goal. Made one save in the shootout.
Cesar Azpilicueta (6/10) – Coped well with the threat of Insigne, but sometimes struggled to contain Emerson.
Eric Garcia (6/10) – Could have done more to prevent Chiesa’s goal. Solid otherwise.
Aymeric Laporte (7/10) – Handled Immobile very well. Unlucky for the goal after a very good challenge to deny Immobile going through.
Jordi Alba (6/10) – As energetic down the left as ever, but couldn’t have the impact in the final third that he usually does.
Sergio Busquets (8/10) – Ran the show in the first half. The calm head in midfield that we’ve come to know over the last decade.
Koke (7/10) – Calm and composed in the middle of the park. Should have had an assist with a lovely pass to Oyarzabal.
Pedri (8/10) – Involved in so much going forward for Spain. Produced a beautiful pass early on which should have led to more.
Ferran Torres (5/10) – Got into a few good positions but couldn’t make the most of them. Substituted on 60 minutes.
Mikel Oyarzabal (6/10) – Always lively and in some great positions, but wasted two huge opportunities.
Dani Olmo (7/10) – Highly involved in the game and got a good assist. Missed a good chance in the first half and also took an awful penalty.
Alvaro Morata (7/10)
Gerard Moreno (6/10)
Marcos Llorente (6/10)
Pau Torres (NA/10)