Lyndon Dykes missed a penalty on a miserable night for QPR at St Andrew’s.
Rangers, who would have returned to the top of the league with a win, trailed two at half-time after goals from Auston Trusty and Emmanuel Longelo.
They had plenty of possession in the second half but struggled to create clean chances before being handed a lifeline when Longelo conceded a 79th-minute penalty with a high challenge on Ethan Laird then that the full-back was trying to reach the center of Ilias Chair.
But goalkeeper John Ruddy dove to his right to fend off Dykes’ kick and dash the visitors’ hopes of a late comeback.
Rangers fell behind after just four minutes when they failed to properly process a corner kick.
Jake Clarke-Salter headed it to Krystian Bielik, who redirected the ball to the penalty spot, where Trusty, with his back to goal, improvised by hooking it over his head and past Seny Dieng, out position, who had come to try to recover the corner.
At the other end, Ruddy fended off Flesh’s free-kick and blocked strikes from Tyler Roberts and Dykes before an eight-minute period in which Rangers were forced to make two substitutions and conceded another goal.
Clarke-Salter limped off after appearing to injure his knee falling awkwardly, shortly before Roberts, back to the side with a calf problem, walked off after suffering a recurrence of the injury.
Longelo then doubled Birmingham’s lead, galloping towards the box and cutting inside Laird before firing past keeper Dieng and into the far corner of the net.
QPR: Dieng, Laird, Balogun, Clarke-Salter (Dickie 21), Paal, Field (Richards 80), Johansen (Amos 45), Iroegbunam, Chair, Roberts (Armstrong 27), Dykes.
Unused submarines: Archer, Kakay, Dozzell.