Ivan Rakitic converted the decisive spot-kick after Mario Fernandes, who had netted an equaliser for Russia with five minutes of extra-time remaining, hit his effort from 12 yards wide.
Denis Cheryshev had put Russia in front in the 31st minute with a superb strike - his fourth goal of the tournament - but that was cancelled out eight minutes later by Andrej Kramaric’s header.
Croatia, having gone close in the 60th minute when Ivan Perisic hit a post, then had the lead in the 11th minute of extra-time as Domagoj Vida nodded in, before Fernandes brought things level late on once again with a header of his own.
Croatia’s win sees them emulate their 1998 achievement of reaching the World Cup’s last four.
They will now take on England at Moscow’s Luzhniki Stadium on Wednesday for a place in the final.
Stanislav Cherchesov’s Russia, meanwhile, will be devastated, but, when the dust settles, can reflect upon a memorable run at these finals.
There was one change apiece to the starting line-ups, with the sole alteration for Russia from their surprise penalty shoot-out triumph over Spain in the last 16 seeing Cheryshev come in for Yuri Zhirkov.
Croatia’s adjustment from their win against Denmark, also on penalties, was former Leicester striker Kramaric replacing Marcelo Brozovic.
Artem Dzyuba had a volley blocked by Dejan Lovren as Russia looked to make an early mark on the game, and an Ante Rebic header and Rakitic free-kick looped over the bar at the other end.
After Perisic sent a header wide of the Russian goal and Cheryshev saw his free-kick easily dealt with, the latter then opened the scoring in stunning fashion.
The Villarreal man played a one-two with Dzyuba, got away from Luka Modric’s attempted tackle and fired in from just outside the box, with Danijel Subasic barely moving.
Cherchesov’s men were then punished for sloppy defending as Kramaric levelled, connecting with Mario Mandzukic’s cross and heading past Igor Akinfeev while the Russian defence did little to stop him.
Kramaric had an overhead kick gathered by Akinfeev shortly after the break and Perisic was then inches away from putting Croatia in front as he saw his strike come back off the inside of a post.
Russia substitute Alexander Erokhin headed over the bar and Modric had a shot blocked before referee Sandro Ricci’s whistle signalled the game was heading into extra-time.
Subasic was clutching at his leg and crying out just prior to that whistle, but he was deemed fit to continue as the additional half-hour got under way.
His side then went ahead for the first time as Vida met Modric’s corner and sent the ball bouncing beyond Akinfeev.
After half-time in extra-time, Subasic got behind behind a fierce Daler Kuzyaev shot and Russia then snatched a dramatic equaliser as Alan Dzagoev swung in a free-kick and Fernandes headed in
The subsequent shoot-out then saw Subasic and Akinfeev make a save each before Fernandes’ miss, which allowed Rakitic to send Croatia through.