Media playback is not supported on this device
With star striker Cristiano Ronaldo missing because of a thigh injury, a cautious Real side offered little goal threat until the closing stages.
But in the last 20 minutes, Jese headed against the bar for the Spanish side before Hart brilliantly denied Casemiro and Pepe from corners.
Hart showed great reactions to keep out Casemiro's header with his foot but his block to deny Pepe, who was unmarked and five yards from goal, is the standout reason City will travel to Spain next week with a precious clean sheet.
The closest City came to a goal of their own was when Keylor Navas tipped over Kevin de Bruyne's dipping free-kick in stoppage time.
Relive a tense first leg at Etihad Stadium
Football Daily podcast: 'A professional European display by Manchester City'
That was Navas' only save of a game that was billed as a shootout between two attacking sides but was, in fact, a game largely devoid of goalmouth action.
City will take the positives from denying Real an away goal but England's last remaining representatives in Europe's elite competition still face a huge task if they are to reach the final, in Milan on 28 May.
Their failure to score at home means former Real boss Manuel Pellegrini does not have a lead to take back to the Bernabeu, where Zinedine Zidane's side have not conceded a goal in the Champions League all season.
The news Ronaldo's thigh muscle was deemed too tight for him to play was clearly a massive boost for City before their first Champions League semi-final.
Without their 47-goal top scorer, a Real side that had scored 133 goals in their previous 46 games this season seemed reluctant to commit men forward and struggled to create chances.
Gareth Bale, playing his first game in England since his £85m move to Real from Spurs in 2013, was unable to provide the spark in Ronaldo's absence.
Bale did get the better of Gael Clichy early on down the right but failed to find a team-mate with his crosses and his finishing was also below his usual standards.
The Wales winger cut in to send one curling shot bouncing wide in the second half but disappointed with a free-kick from the edge of the box which he fired against the City wall.
Both of Real's late chances came from set-pieces and they struggled to open up City.
The home side were not helped by David Silva being forced off by injury before half-time and were short of their customary zip in the final third.
Sergio Aguero was starved of service and only managed one shot at goal, which came when he fired over from the edge of the box at the start of the second half.
The former Atletico Madrid striker has now played Real 13 times in his career and has still never beaten them, but will get another chance on Wednesday, 4 May.
In truth, City's whole attack will have to do better in the second leg.
De Bruyne, who started in the number 10 role but ended up on the left after Silva's injury, was also short of inspiration, Jesus Navas made few inroads down the right and Kelechi Iheanacho's pace had little impact.
Manchester City boss Manuel Pellegrini:
"We played a very intense game and defended well. We tried to create until David Silva got injured then we lost the ball too much. If you cannot win then a 0-0 draw is good.
"We knew they were going to play a slow game and that is why we pressed as a team. When we had the ball, we could not make the difference. We could not score."
Media playback is not supported on this device
Manchester City captain Vincent Kompany:
"It is too close to call at the moment - 0-0 is a very dangerous scoreline.
"From the moment we manage to score in Madrid, it will be very different.
"It is hard to keep a clean sheet against such an attacking team. We can be proud of what we have achieved in this first leg."
The first leg of the other semi-final, between Atletico Madrid and Bayern Munich, takes place in Spain on Wednesday.
Before their trip to Madrid, City travel to Southampton on Sunday in a 16:30 BST kick-off. With three league games remaining, Pellegrini's side are still in need of Premier League points to secure a top-four finish that will make sure of Champions League football next season too.
Real, third in La Liga and a point behind leaders Barcelona, are already certain of their Champions League place but are still in the title race. They also have an away game this weekend - against Real Sociedad at 15:00 BST on Saturday.
Match ends, Manchester City 0, Real Madrid 0.
Second Half ends, Manchester City 0, Real Madrid 0.
Corner,  Manchester City. Conceded by Keylor Navas.
Attempt saved. Kevin De Bruyne (Manchester City) right footed shot from a difficult angle and long range on the left is saved in the top centre of the goal.
Daniel Carvajal (Real Madrid) is shown the yellow card for a bad foul.
Foul by Daniel Carvajal (Real Madrid).
Kevin De Bruyne (Manchester City) wins a free kick on the left wing.
Isco (Real Madrid) wins a free kick in the defensive half.
Foul by Fernandinho (Manchester City).
Substitution, Real Madrid. Isco replaces Toni Kroos.
Foul by Lucas Vázquez (Real Madrid).
Gaël Clichy (Manchester City) wins a free kick in the defensive half.
Pepe (Real Madrid) wins a free kick in the defensive half.
Foul by Fernando (Manchester City).
Attempt blocked. Gareth Bale (Real Madrid) left footed shot from the centre of the box is blocked.
Attempt saved. Pepe (Real Madrid) left footed shot from very close range is saved in the centre of the goal. Assisted by Gareth Bale.
Attempt missed. Gareth Bale (Real Madrid) header from the centre of the box misses to the right. Assisted by Toni Kroos with a cross following a corner.
Corner,  Real Madrid. Conceded by Vincent Kompany.
Attempt blocked. Gareth Bale (Real Madrid) left footed shot from outside the box is blocked.
Marcelo (Real Madrid) wins a free kick in the attacking half.
Foul by Fernando (Manchester City).
Attempt saved. Casemiro (Real Madrid) header from the centre of the box is saved in the centre of the goal. Assisted by Toni Kroos with a cross.
Corner,  Real Madrid. Conceded by Bacary Sagna.
Substitution, Manchester City. Raheem Sterling replaces Jesús Navas.
Attempt missed. Gareth Bale (Real Madrid) left footed shot from the right side of the box misses to the left. Assisted by Toni Kroos.
Attempt missed. Luka Modric (Real Madrid) right footed shot from outside the box is too high. Assisted by Gareth Bale.
Jesé (Real Madrid) hits the bar with a header from the centre of the box. Assisted by Daniel Carvajal with a cross.
Corner,  Manchester City. Conceded by Gareth Bale.
Foul by Lucas Vázquez (Real Madrid).
Kevin De Bruyne (Manchester City) wins a free kick on the left wing.
Attempt missed. Toni Kroos (Real Madrid) right footed shot from outside the box is close, but misses to the left.
Casemiro (Real Madrid) wins a free kick in the defensive half.
Foul by Jesús Navas (Manchester City).
Foul by Pepe (Real Madrid).
Sergio Agüero (Manchester City) wins a free kick on the left wing.
Foul by Marcelo (Real Madrid).
Jesús Navas (Manchester City) wins a free kick in the defensive half.
Attempt blocked. Marcelo (Real Madrid) left footed shot from outside the box is blocked. Assisted by Casemiro.
Daniel Carvajal (Real Madrid) wins a free kick in the defensive half.
Foul by Sergio Agüero (Manchester City).
Joe Hart kept Manchester City's hopes of reaching their first Champions League final alive with two brilliant late saves that ensured their semi-final first leg with Real Madrid finished goalless.