Rishabh Pant hit a brilliant 100 not out for India on a difficult pitch on Friday but the decisive final Test was still in the balance as South Africa went to stumps on 101-2, needing 111 more runs to win the match and take the series.
South Africa made good progress toward that victory late on Day 3 as Dean Elgar and Keegan Petersen put on a 78-run stand after the early loss of opener Aiden Markram.
But Elgar was out to an edge down the legside on what turned out to be the last ball of the day to give India renewed hope in its quest to finally win a test series in South Africa.
South Africa captain Elgar's dismissal was confirmed via a review and India captain Virat Kohli jumped for joy when it was clear that his opposite number was on his way for 30. Elgar was South Africa's match-winner in the second test to level the three-match series 1-1 and set up the decider at Newlands in Cape Town.
The series has been tight and low-scoring throughout. In this test, top-ranked India batted first and made 223, South Africa replied with 210 and India made 198 in its second innings to set the home team a target of 212 to take the series.
Petersen was 48 not out at the close.
Earlier, Pant's fourth test century was priceless for India. No other India batsman could master the Newlands surface, with Kohli's 29 the next-best score and the only other score over 10.
Pant hit six fours and four sixes in a flashing innings typical of his style, and also after coming in with India under pressure at 58-4 having lost two wickets in the first two overs of the day.
The left-hander reached his century just in time, with India nine wickets down and last man Jasprit Bumrah hanging in alongside him. Bumrah was out soon after for 2 and South Africa took six wickets in the second session to set up an intriguing finish to the series.
The Proteas could win with a successful fourth-innings chase just like they did to level the series in Johannesburg.
India's lead didn't come easily.
South Africa struck twice in the first two overs of the day in a blistering start. Cheteshwar Pujara was out for 9 on the second ball of the day and to a flying catch at leg slip by Petersen. Ajinkya Rahane followed for 1 in the next over.
Kohli played an exceptionally cautious innings as his 29 came from 143 deliveries at a strike rate of just 20, an unusually defensive effort from one of the world's most talented batsmen.
But it was what India needed after those early blows. With Kohli being careful, and Pant playing his natural attacking game, they put on 94 for the fifth wicket to make sure India had a chance.
Kohli fell soon after lunch and the rest of the India lineup followed quickly, with the exception of Pant. He blazed a lofted shot down the ground when on 94 and was dropped by Temba Bavuma, who dived forward to attempt a tough catch and the ball burst through his hands.
Pant got to his 100 soon after with a dab down to square leg for a single.
India set an unusual record when Bumrah was caught by Bavuma to end the innings. It became the first team in test cricket history to lose all 20 of its wickets in a match to catches.