An enthralling encounter at the Etihad Stadium eventually saw City go top of the Premier League table for the first time this season.
Ahead of Manchester United's game at Fulham, in which a win will see them leapfrog their rivals, City and Villa pushed each other from end to end.
Villa were playing their first game in three weeks due to a severe Covid outbreak at the club, but showed little signs of rust.
Both sides were guilty of spurning chances, though City were most guilty before Bernardo Silva scored his first goal of the season just over 10 minutes from time.
Villa cried offside, manager Dean Smith was sent from the stands for protesting, but the goal stood. The Premier League quickly clarified why the decision was correct.
Ilkay Gundogan ended Villa's hopes with an injury time penalty.
Relive the game below with Standard Sport's live blog.