Vettel controlled proceedings from the start, but the race opened up when Ferrari and Mercedes opted for differing strategies at their first pit stops. Ferrari chose the soft tyres, Mercedes the mediums.
While Mercedes could go to the end comfortably, it was more of a stretch for Vettel, allowing Bottas to close up and create a grandstand finish. Ultimately, Bottas ran out of laps and Vettel held on to secure his 49th victory in his 200th Grand Prix start.
Hamilton delivered a brilliant comeback drive from ninth on the grid to complete the podium, but there was heartbreak for Red Bull as Daniel Ricciardo and Max Verstappen retired for separate reasons within minutes of the race starting.
Vettel led away from pole, with Bottas making use of starting on the clean side of the grid to beat Raikkonen to Turn 1 to take second.
Hamilton, who had started ninth after a five-place grid penalty, kept his nose clean at the start, but was passed by Alonso and then came under attack from Verstappen.
Verstappen launched his Red Bull up the inside into Turn 1 and gave Hamilton the squeeze. But in running the Mercedes driver out of road, the duo made contact and Verstappen picked up a puncture.
It was a disastrous few moments for Red Bull as Ricciardo pulled off track with a suspected electrical issue, triggering the virtual safety car.
Verstappen made it back to the pits, but though the team got him back out, car damage ultimately forced him out of the race, sparking Red Bull’s first double retirement since the 2010 Korean Grand Prix.
When normal race conditions resumed, Vettel led away from Bottas ahead of Raikkonen, Gasly and Magnussen.
After a sluggish start, Hamilton’s race exploded into life as he passed three cars into one corner. He used DRS to pass Alonso on the straight and then passed both Ocon and Hulkenberg who were squabbling on the approach to Turn 1.
The reigning world champion then passed Gasly for fourth, leaving him 14 seconds off the lead.
Vettel was the first to blink on lap 18, pitting for softs and rejoining fourth. Raikkonen followed the next lap, mirroring his team mate’s strategy. Bottas came in a lap later, but Mercedes mixed it up by fitting his car with the medium tyres.
Hamilton stayed out a further seven laps before surrendering the lead, pitting for the mediums and re-joining in fourth.
At this stage, Mercedes looked set to go to the end, with Ferrari potentially needing to pit again. The latter turned out to be the case for Raikkonen on lap 36.
But disaster struck as Raikkonen’s car was dropped from the jack before the left-rear wheel had been changed. The Finn pulled away, hitting one of the mechanics.
As the mechanic – later confirmed to have suffered a shinbone and fibula fracture – was tended to, Raikkonen was instructed to stop the car just metres from his pit box, after what was his second unsafe release of the weekend, following on from the one in practice.
Up front, Vettel built a lead of 7.5s over Bottas, with Hamilton a further 9.1s back in third. The reigning world champion was then told by Mercedes that they thought Vettel would try to go to the end.
With that in mind, Bottas was told to start closing Vettel down while radio problems made communication between Hamilton and his team difficult, with the Briton growing frustrated by a lack of information regarding the strategy.
Bottas cut the gap to 5.9s with nine laps to go, with Vettel complaining on team radio that he was not getting assistance from blue flags as he tried to battle through traffic.
He kept cutting the deficit, getting to within a second – and therefore DRS overtaking range – with two laps to go to set up a dramatic finish.
As they headed into the first corner on the final lap, Bottas had a half-hearted attack but he was just not close enough. The chance of the win disappeared and Vettel held on to clinch victory.
Hamilton crossed the line third, with Gasly finishing a sensational fourth to give Honda their best result since returning to F1 and give Toro Rosso only their 10th top-five finish.
Magnussen took an impressive fifth for Haas, ahead of Hulkenberg while McLaren scored a double points finish for the second successive race with Fernando Alonso and Stoffel Vandoorne seventh and eighth respectively.
Sauber’s Marcus Ericsson ended a 50-race streak without scoring points in ninth and Ocon was rewarded for his relentless attack of Sainz, snatching 10th and the final point.