With India taking the lead before lunch, the hosts bagged the last three required scalps to dismiss the opposition half an hour before tea.
Ajinkya Rahane, who made his maiden Test half-century in the first innings, produced a lone fight in an effort to hold off the Proteas bowlers, but he received little support.
Spinner Robin Peterson trapped Zaheer Khan lbw for three runs and Dale Steyn had Ishant Sharma caught behind for one to secure his 350th Test wicket.
The speedster reached the milestone from 130 innings. Only retired Sri Lankan Muttiah Muralitharan (120 innings) has achieved the feat earlier in his career.
Rahane was the last man out, falling four runs short of his maiden Test century as Vernon Philander clipped his leg stump, after spending nearly four hours at the crease in a defiant innings that included 11 fours and two sixes.
Steyn led the Proteas attack, returning 3/47 for match figures of 9/147. Peterson took 4/74 and Philander grabbed 3/43.
Earlier, the hosts had grabbed five wickets in the morning session as they ripped through India’s middle order to leave the tourists reeling.
Steyn produced an early double strike to put India on the back foot after they resumed at 68/2, trailing South Africa by 98 runs.
The paceman removed Virat Kohli with the first ball of the day when the top-order batsman was caught behind for 11 runs.
While Kohli clearly felt aggrieved by the decision, and replays showed the ball clipped his arm, with India’s refusal to adopt the decision review system he was forced to return to the dressing room.
In his next over, Steyn dislodged Cheteshwar Pujara’s off stump for 32 runs and India were in trouble as their chances of holding on for a draw began to fade.
Rahane and Rohit Sharma attempted to stabilise the innings but Philander broke their 33-run stand for the fifth wicket when he trapped Sharma leg-before for 25 runs.
Rahane then combined with Indian skipper MS Dhoni in a 42-run partnership before Peterson got the breakthough with a double strike half an hour before the lunch break.
Peterson dismissed Dhoni, who made 15, and Ravindra Jadeja, who contributed eight runs, in the same over as both batsmen gifted the hosts their wickets with simple catches to put their side on the back foot.