McLaren's Carlos Sainz was the only non-starter of the race, as an exhaust failure ended his chances while the Spaniard was on his way to the grid.
Hamilton held the lead from pole despite a challenge from Bottas into Le Source, while Daniel Ricciardo looked to get pass Verstappen into Les Combes, but could not make the move stick.
The Ferrari started dropping down the order, with Leclerc complaining of poor speed on the straights, falling back as far as twelfth on the tenth lap.
The safety car was deployed after a accident for Antonio Giovinazzi and George Russell at Les Fagnes. Giovinazzi spun on the exit of the corner and hit the barriers, leaving Russell with nowhere to go, hitting a wheel from Giovinazzi's accident. Both drivers emerged from the cars unhurt.
All drivers decided to pit during the safety car, with the exception of Gasly and Perez. Only Alexander Albon changed to mediums during the stops, with the preferred compound for drivers being hard tyres in the hopes of going to the end.
The safety car returned to the pits and racing resumed on lap 15, Hamilton led away but Bottas came under pressure from Verstappen. as Gasly fended off Perez behind.
Hamilton reported a loss of power from his car, with Bottas closing the gap on his teammate. His team told him it was energy management from the power unit, and he should be fine to continue.
Perez slipped down the order on his older tyres thanks to overtakes from Ricciardo and Albon. Perez opted to pit on lap 19, putting the Racing Point at the bottom of the remaining cars.
Sebastian Vettel and Leclerc almost came together at Les Combes as Vettel squeezed his teammate when Leclerc tried to challenge for twelfth position.
Gasly conceded his fourth place to Ricciardo on lap 22, as sixth-placed Albon closed up on the AlphaTauri ahead. After a few laps behind Gasly, Albon eventually made his way past on lap 24 for fifth. Mercedes reported dropping track temperatures as the clouds closed in around the circuit.
Meanwhile, Leclerc made a second stop for mediums on lap 25, but as his first stop under the safety car, it was a slow stop for the Ferrari driver, with the mechanics topping his car up with what looked to be hydraulic pressure during the stop. Ferrari would not reveal what it was, preferring to tell Leclerc after the race.
Gasly pitted on lap 27, with AlphaTauri believing the rest of the field will not be able to finish the race on a one-stop strategy. Verstappen reported vibrations on his set of hard tyres, as Ferrari confirmed pneumatic pressure was what the team were adding to Leclerc's car as he pitted.
Vettel locked up and had to go wide at Les Combes trying to defend his twelfth position from a recovering Gasly, as Perez moved into the points at the expense of Kimi Raikkonen on lap 33, as Gasly did the same on the Alfa Romeo the following lap.
Bottas reported numbness from his left leg on the brakes, as Verstappen behind noticed his tyre vibrations were worsening. Both Mercedes drivers were beginning to struggle with tyre wear with seven laps to go, with Gasly being let by Kvyat due to being on a faster strategy.
Hamilton went wide after locking up at the Bus Stop chicane, while also briefly sliding coming through La Source, while Bottas was told to stay away from the kerbs in order to preserve his tyres, the Finn also locking up and going wide at the Bus Stop.
With two laps to do, Ricciardo started setting personal best lap times, while Ocon could not find a way around Albon. With the pair battling, McLaren's Norris was able to catch up and challenge.
On the final lap, Albon lost out to Ocon for fifth, with Albon now holding Norris behind as Hamilton came home to take the win ahead of Bottas and Verstappen. On the final lap, Ricciardo took the fastest lap, only being three seconds behind Verstappen at the end.
Eighth and ninth went to Gasly and Lance Stroll, while Perez rounded out the top ten and took the final point.
Bahrain International Circuit - Winter testing