Pole-sitter Daniel Ricciardo crossed the line of a fascinating weather-hit race in second while Force India’s Sergio Perez completed the podium places.
Championship leader Nico Rosberg struggled in the early wet conditions – at one stage he was instructed by Mercedes to move over for a much-faster Hamilton – and finished seventh, 93 seconds behind his team-mate, after Nico Hulkenberg pipped him on the line.
It allowed Hamilton, who ended an eight-race losing streak here, to slash the gap to Rosberg to 24 points in his quest to become the only British driver to win four championships.
The drama-fuelled race started under a safety car following a deluge of rain at the principality, and while the entire field pitted for intermediate tyres, Hamilton took what would be the race-winning decision to stay out on the extreme wet option.
It enabled the world champion to take control at a track where overtaking is virtually impossible, before he eventually stopped for dry rubber on lap 31.
Ricciardo pitted one lap later, but his pit crew were inexplicably not ready for him, and he emerged behind the British driver.
It was a blunder, which the Red Bull team later blamed on a “miscommunication”, and one which would ultimately cost Ricciardo his first victory in nearly two years.
The Australian, who had started on pole, attempted to pass Hamilton after the world champion made a mistake at the chicane, but the Briton afforded him little room. Ricciardo waved his hand furiously at Hamilton, but the incident was subsequently investigated by the stewards who took no further action.
Ricciardo kept Hamilton honest over the remaining laps, but was unable to find a way past. The gap as they crossed the line was more than seven seconds.
Sebastian Vettel was fourth for Ferrari.
Jenson Button completed a double-points finish for McLaren on the team’s 50th anniversary after he crossed the line in ninth place.
Page 3: 15:28A distraught Ricciardo, who looked certain to win in Spain a fortnight ago until Red Bull pitted him one more time than his team-mate Verstappen, cut a disconsolate figure.
“The race shouldn’t have been as exciting as it was to be honest,” he said. “Two weekends in a row now I have been screwed. It sucks. It hurts.”
Asked about the pit-stop blunder, he added: “I have no idea. I was called into the box. I didn’t make the call. They should have been ready.”