Zaha struck after just six minutes when Conor Gallagher robbed Aymeric Laporte inside his own half before Gallagher wrapped up the points when he fired home two minutes from time.
Laporte was red-carded by referee Andre Marriner in first-half stoppage time when he committed a professional foul by bringing down Zaha 35 yards from the City goal.
Even a man down, the hosts remained a goal threat and Gabriel Jesus thought he had levelled when he turned home Phil Foden’s superb far-post cross, only for video assistant referee Lee Mason to rule the England forward was offside in the build-up.
City fans were infuriated by what they saw as time-wasting from Palace, which started in the opening period, and manager Pep Guardiola – marking his 200th match in the Premier League as a manager – was less than impressed with what he saw too, judging by the number of times he spoke to fourth official Anthony Taylor.
But Palace were a danger on the break, with Jordan Ayew and Gallagher both wasting decent chances before Gallagher finished Michael Olise’s lay-off to give Patrick Vieira’s men victory and end a frustrating run of four consecutive Premier League draws.
Man City defending falls short
City’s defence had been virtually watertight this season but there was an element of over-confidence that led to Palace’s breakthrough.
Laporte had lots of space and time to decide what to do with the ball as he advanced towards the halfway line. But he didn’t react as Gallagher closed in and a quick exchange of passes later, Zaha was through.
The contact wasn’t the greatest but the accuracy was there and the shot found the bottom corner.
It was the first Premier League goal City had conceded at home all season and only their fourth in the top flight in total.
Laporte’s dismissal made their task harder an d Bernardo Silva and Jesus both needed to be calmed down as the half-time whistle blew, even though the Spain defender’s only complaint could be the distance from his own goal that the offence took place.
Although Palace memorably won at this ground in December 2018, it was their only positive result in 12 trips to Etihad Stadium that otherwise yielded just two points.
For Vieira, victory was particularly special, partly because of the time he spent at City as both a player and a youth-team coach, but mainly because of the nasty habit his side had developed of giving away leads late in games.
Zaha’s goal was the fourth time in five matches they had been in front – yet they had failed to win any of the previous three.
Yet again, Gallagher was superb in midfield, his energy helping to shield a defence who, at times, did exceptionally well not to be lured into giving away a penalty, in particular by the close control of Bernardo and Jack Grealish.
By the time Gallagher scored, Palace had weathered the storm as City slipped five points behind leaders Chelsea.
Manchester City are next in action against Belgian side Club Bruges in the Champions League on Wednesday, 3 November (20:00 GMT). Their next Premier League game is at Manchester United on Saturday, 6 November (12:30).
Crystal Palace’s next game is against Wolves at Selhurst Park, also on 6 November (15:00).