It looked like being an easy day for the hosts when Zimbabwe crashed to 117 all out, their lowest total in 39 one-day internationals between the two countries.
But South Africa also struggled on a pitch of variable and occasionally steep bounce, losing their first four wickets for 58 runs before a hard-hit 44 by wicketkeeper Heinrich Klaasen took them most of the way to the win.
"It was a very indifferent wicket," said stand-in South African captain JP Duminy. "There was always something in it for the bowlers. Even though we bowled well it was quite a tough total to chase down."
Opening bowler Lungi Ngidi took three for 19 to lead a potent South African bowling performance after Duminy sent Zimbabwe in to bat.
"It was about keeping it simple, hitting your lengths and the wicket will do the rest," said Ngidi, who was named man of the match.
Duminy's decision to bowl paid off almost immediately when Solomon Mire was caught at second slip off Ngidi without scoring.
Although captain Hamilton Masakadza made 25 and Elton Chigumbura hit 27, Zimbabwe were unable to put together any substantial partnerships as the South African bowlers maintained control.
"We were surprised how it played," said Masakadza. "If we had scored another 50 or 60 runs we would have been more competitive."
Kagiso Rabada, Andile Phehlukwayo and leg-spinner took two wickets apiece to back up Ngidi.
Zimbabwe may have been unfortunate when Craig Ervine was the second batsman to fall, given out caught behind off Wiaan Mulder when replays suggested the ball may have missed his bat. No decision review system is in place in this low-profile series.
Tendai Chatara bowled an impressive opening spell, taking two for 12 in six overs to raise Zimbabwe's hopes before Klaasen took charge. Klaasen hit 44 off 44 balls before he was fifth man out with 22 runs still needed.
Klaasen hit two successive sixes off left-arm spinner Wellington Masakadza before he was caught in the deep trying to hit a third.
First Published: September 30, 2018, 8:32 PM IST