Federico Valverde slotted in the winner after Ansu Fati’s late equaliser forced extra time in Saudi Arabia.
In a thrilling El Clasico clash, Real took the lead three times, with Barca coming back twice before Valverde eventually made it 3-2.
Real striker Karim Benzema scored and assisted in normal time, but Luuk de Jong and Fati levelled in each half.
Benzema, who played in Vinicius Junior for the 25th-minute opener, also hit the post in normal time and came close to extending Real’s lead with minutes to go in extra time.
He was a threat throughout, while Vinicius’ pace on the counter-attack caused problems for Barcelona.
But Xavi’s side also created opportunities, especially through Ousmane Dembele and substitutes Pedri and Fati, though they were unable to capitalise on them.
There was also a full Barcelona debut for former Manchester City forward Ferran Torres, returning from injury, but he did not get on the scoresheet before being substituted at half-time.
Last season’s La Liga champions Atletico Madrid take on Athletic Bilbao on Thursday in the other semi-final, with the winner facing Real Madrid – chasing their 12th Super Cup – in Sunday’s final in Riyadh.