After a forgettable first half, the second period was one to remember with the visitors taking the lead through substitute Jack Grealish an hour in.
The Premier League champions then looked to be in cruise control before the Red Devils sprung back into life in the last 15 minutes.
Bruno Fernandes equalised on 78 minutes after it appeared that his goal would be ruled out for a Marcus Rashford offside, but the England forward was deemed not to be interfering in play, much to the chagrin of Manchester City’s defenders who expected a flag.
Rashford then netted the winner five minutes later after excellent play from Alejandro Garnacho on the left flank found him six yards out to poke past Ederson.
City were shell-shocked late on after the dramatic response seemingly from nowhere from their hosts and could do little to respond as United held on for a famous victory.
It was a tight first half during which City unsurprisingly had the majority of possession but United undoubtedly had the better chance.
Marcus Rashford had the best two opportunities but couldn’t convert either and it took over half an hour before the England star nearly struck.
Just after the half hour mark, Rashford chased a ball over the City defence as Ederson ran out of his goal and saw the forward flick the ball past him.
It looked for a moment like Rashford would have an open net to finish into but he had been forced wide and when he was set to shoot defenders were back on the line and his effort was cleared.
Five minutes later Rashford was played in behind the City back four again, as Christian Eriksen found him, but a heavy touch from the striker saw Ederson smother his poked strike.
There was concern for the United star shortly after when he went down with a hip problem, but he limped on.
Manchester City’s only real effort of note in the opening 45 minutes came with the last kick of the first half when Kyle Walker hit a decent strike from range but it flashed wide.
Anthony Martial was replaced by Antony at the break for United, but City were the changed side in the second half, looking livelier and starting to stamp their authority on the match.
Pep Guardiola’s side were not really creating clear chances, but they were growing in stature and when they did cut through on 60 minutes, they took full advantage with their first shot on target.
Nice work on the right from Riyad Mahrez played in Kevin De Bruyne in the box and the Belgian produced typical quality to beat Casemiro and stand the ball up onto the onrushing head of Jack Grealish, who had only just replaced Phil Foden from the bench.
The goal seemed to drain the confidence of United a bit and they were not creating much at all until suddenly the game was level on 78 minutes, in dramatic style.
Marcus Rashford was played in behind the City defence and obviously offside, but at the last moment before getting onto the ball he left it for Bruno Fernandes who had burst on from midfield.
The Portuguese finished impressively but the City defenders assumed Rashford would be given offside. As he didn’t touch the ball, or impede opponents playing the ball, though, it did not happen.
United were level and just four minutes later they were sensationally ahead, with Rashford getting on the scoresheet this time.
Substitute Alejandro Garnacho was played in down the left and after two bites at the cherry to cross the ball, he picked out Rashford six yards out who finished coolly.
There was a penalty claim for a challenge on Erling Haaland but City could muster little to trouble David De Gea late on and succumbed to defeat.
United climb to third in the table ahead of Newcastle, while City stay second, five points behind Arsenal.
The Red Devils are now within six points of the Premier League-leading Gunners and can start to dream of an unlikely title challenge.
For more stories like this, check our sport page.