The Ferrari man took advantage of an early safety car as he hit the front and held off Hamilton and Nico Rosberg after pitting only twice, compared to three for the Mercedes pair.
The four-time world champion now has 40 career wins but it is his first with Ferrari, and breaks a dry spell stretching back to his last race with Red Bull in 2013.
Few of his wins can have been as satisfying. He shattered assumptions of Mercedes' unassailable superiority in 2015, after they dominated the season-opener in Australia.
Further back, there were also celebrations for Max Verstappen as the 17-year-old finished seventh, becoming the youngest points-scorer in Formula One history.
Hamilton got away smoothly from pole and Vettel aggressively defended second from a charging Rosberg, helped by a nudge against the Mercedes as they battled round the first corner.
Kimi Raikkonen and Pastor Maldonado were quickly hit by punctures, and Sauber's Marcus Ericsson lasted just three laps before he spun off on Turn 1, prompting the safety car.
When Vettel finally pitted after lap 17, he re-emerged behind the two Mercedes but he set the day's fastest lap so far and scorched past his fellow German at the end of lap 21.
Vettel was on Hamilton's tailpipe when the Briton made his second stop at the end of lap 25, dropping back behind the Ferrari driver and Rosberg.
Rosberg pitted to promote Hamilton to second, and the Briton floored it with a pair of fastest laps as he set about whittling away Vettel's big lead of more than 20 seconds.
Vettel and then Hamilton pitted on consecutive laps and the Briton complained "This is the wrong tyre!"as he resumed on the hard compound.
"I don't know what I'm supposed to be doing!" he shouted, after hearing perplexing chatter on the radio which appeared to suggest a third stop.
