The India captain was unbeaten on 194, and in a 97-run partnership for the fifth wicket with Ravindra Jadeja (25).
Kohli reached his 26th test hundred — and first since December 2018, when he scored 123 against Australia — off 173 deliveries prior to lunch, which India took on 356-3.
Kohli set a quick pace in the second session, scoring his next fifty in 68 runs and moving to 28 fours for his innings by tea.
Kohli put on 178 runs for the fourth wicket with Ajinkya Rahane (59), who was caught behind off Keshav Maharaj (1-155) for the spinner's 100th wicket in his 27th test.
The South Africans couldn't build on that breakthrough as Jadeja defied them for a whole session. It was a surprising move to send in Jadeja at No. 6, with wicketkeeper-batsman Wriddhiman Saha held back.
On day one, Mayank Agarwal (108) scored his second test century.
India leads the three-match series 1-0 after winning the first test in Visakhapatnam by 203 runs.