Williamson, the New Zealand skipper, was subjected to immense pressure from pacemen Kagiso Rabada, Vernon Philander and Morne Morkel but reached 78 not out at stumps with nightwatchman Jeetan Patel alongside him on nine at University Oval in Dunedin.
New Zealand could have been even better placed had Ross Taylor not retired hurt with a calf injury while on eight and the hosts 148 for two.
South Africa had been bowled out for 308 shortly after lunch when Trent Boult (4-64) dismissed Philander for 21 to pick up his fourth wicket of the innings.
Philander got an early breakthrough when Tom Latham was caught behind by Quinton de Kock for 10 as the pace trio embarked on a war of attrition with Williamson and opener Jeet Raval.
The 31-year-old Philander and Williamson engaged in a fascinating battle, with the bowler hammering away on a good length at off stump.
Williamson, however, managed to see off Philander's initial spell and when left-arm spinner Keshav Maharaj was introduced, the New Zealand pair began to free up, despite having to deal with the extra bounce from Morkel.
The reached 59 for one at tea then capitalised in the final session, Raval reaching his third Test half century with a punch down the ground off Maharaj for his sixth boundary.
Williamson brought up his 26th Test half century with three successive boundaries from Rabada, which also brought up the century-partnership with Raval.
Opener Raval was dismissed for 52 in the next over as he looked to work away a delivery from Maharaj only to pick out Dean Elgar at short midwicket instead.
Henry Nicholls was the other wicket to fall, brilliantly caught by Hashim Amla at slip off Maharaj for 12.
New Zealand had earlier taken the last six South African wickets for 79 runs in a little over two hours, with four falling in the first session, including Elgar for 140 and Temba Bavuma for 64 after they had compiled a 104-run partnership.
308 in 122.4 overs (Elgar 140, Boult 4/64)
lead New Zealand
177/3 in 55 overs (Williamson 78*, Raval 52) by 131 runs