Hamilton took his 100th pole on Saturday but couldn’t hold the lead on the first lap, with Verstappen getting the better launch and cutting down the inside of the Mercedes at the first turn.
The Dutchman made an early break, but the Briton made steady gains in the first stint to get back within a second on lap 25, in time for the first pit stop window.
Red Bull Racing pre-empted a Mercedes move by pitting Verstappen, but Mercedes held its nerve, keeping Hamilton out on old tyres until lap 29.
He emerged with a six-second gap to the lead, but the winds were starting to turn in Spain. On fresh rubber Hamilton was substantially faster than Verstappen, and in only three laps he was all over the back of Verstappen and haranguing him for the lead.
But passing is difficult at the Circuit de Barcelona-Catalunya, and the longer the pair ran on their tyres, the less of an advantage Hamilton’s newer rubber offered.
It was then that the Mercedes pit wall pulled a blinder, hauling Hamilton into the pits for a surprise second stop on lap 43, handing him 23-second deficit with 23 laps to close and pass.
Such was Hamilton’s pace - and so ailing were Verstappen’s tyres - that he got the job done in just 17, allowing him to cruise home in the final six laps to claim a 98th career victory.
“I feel great after this. I feel like we could go again,” a jubilant Hamilton said. “It was a long way to come back from 20-odd seconds back, but it was a good gamble. Really great strategy by the team.
“Just a remarkable job by everyone here in this team through and through. What a day.”
With three wins and a second place from the first four races, this is Hamilton’s strongest start to a season in his career, and he now leads the championship by 14 points.
Verstappen was stoic in defeat, the Dutchman admitting that the challenging and technical Barcelona track proved Red Bull Racing remains a step behind Mercedes in pure pace.
“In a way I could see it coming,” he said. “There was not much we could’ve done.
“It shows we are not where we want to be. We have to push hard and catch up because we are a little bit slower.”
Valtteri Bottas finished a distant third in the second Mercedes after falling to fourth on the first lap behind Ferrari’s Charles Leclerc. Within a matter of laps he’d lost touch with the battle for the lead, and though he was able to strategise his way past the slower red car, he was 26 seconds off the lead by the time he reached the flag.
“It’s a bit of a shame, but at least we made it to the podium,” he said. “As a team we’re still scoring solid points but not perfect points, so there’s still work to do.”
Leclerc came home a strong fourth for Ferrari in a race quiet once Bottas found a way through to the podium.
Sergio Perez recovered from eighth on the grid to finish fifth. The Mexican spent much of the race behind McLaren’s Daniel Ricciardo before snatching the place from the Australian with a bold late-braking move around the outside of turn one.
Ricciardo came home sixth, equalling his best result for McLaren this season in a much improved performance after a difficult start to his career in orange.
Carlos Sainz followed Ricciardo over the line less than a second adrift for seventh ahead of Lando Norris in the second McLaren.
Esteban Ocon lost places late for Alpine thanks to an overly ambitious tyre strategy to finish ninth, and Pierre Gasly score one point for 10th for AlphaTauri.