VVS Laxman hit the only half-century of the match to give India the upperhand against South Africa, on Day 3 at Kingsmead, Durban, on Tuesday.
Chasing a stiff 303 for victory, South Africa were 111 for three in 27 overs with AB de Villiers on 17 and Jacques Kallis on 12 before bad light closed play early on the third day.
S Sreesanth pegged back the hosts after a good start as he took two for 30 in seven overs including the wickets of Graeme Smith and Hashim Amla, while Harbhajan Singh claimed the other wicket to fall, that of Alviro Petersen.
Smith smashed a quick 37 from 38 balls before he top edge a pull shot against Sreesanth, while Amla failed in the second innings too when he was caught behind for 16 off the Kerala pacer.
Earlier, VVS Laxman fell short of a deserved century to help India post 228 in their second innings. The veteran hit a fluent 96 from 171 balls, having hit 12 fours, before he was the last wicket to fall, caught behind off pacer Dale Steyn.
The lower order gave Laxman good support as the last three wickets put on 80 runs with Zaheer Khan contributing with a good knock of 27.
Lonwabo Tsotsobe was the most successful bowler for the hosts as he took three for 43, while Morne Morkel claimed three for 47. Steyn bagged two for 60 to end with eight wickets in the match, but spinner Paul Harris got only a solitary wicket.
On Monday, Harbhajan took four wickets and Zaheer Khan three as South Africa were dismissed for a paltry 131 in 37.2 overs, after India's first innings folded for 205 in 65.1 overs earlier in the day which saw 18 wickets falling.
Zaheer showed the way with a remarkable spell of three for 29, while Harbhajan ran through the middle and lower order for wonderful figures of four for 10 in 7.2 overs.
India's fielding also rose to the occasion, some unbelievable catches being taken.
Hashim Amla was South Africa's top-scorer with 33 and Alviro Petersen made 24; no other batsman could cross the 20-run mark.
Morning session: (126 runs, 31.1 overs, 3 wickets)
South Africa struck an early blow on the third day when Morkel claimed the wicket of Pujara for 10. The youngster, who showed great patience during his 81-minute stay at the crease, tried to keep down a bouncer but it hit the handle of his bat and crashed on to the stumps.
Dhoni showed an aggressive intent as he cracked Morkel down the ground for a four, off the third ball he faced. India's captain then pulled Steyn over square leg and slammed the next ball through point for back-to-back boundaries in the next over.
Laxman also kept the boundaries coming; he played the late cut over slips against Morkel, and was lucky against Tsotsobe when his thick outside edge, as he tried to play a full delivery on the leg side, went over the slips for another four. It took India's lead past 200.
But Tsotsobe again delivered a crucial blow with the ball. He tempted Dhoni to push at an outgoing delivery, which he edged behind to wicketkeeper Boucher after scoring 21 from 35 balls.
Dhoni and Laxman's partnership of 48 from 60 balls for the sixth wicket helped India recover slightly and push towards a sizeable total.
Harbhajan failed to make a contribution with the bat, scoring just four before he edged Morkel straight into the hands of Kallis at second slip.
Zaheer appeared in no mood to stay at the wicket. He tried a few wild swipes against the pacers before hitting a full delivery from Tsotsobe through midwicket for a four which brought up his 1000 runs in Test cricket, in his 77th match.
Laxman brought up the first fifty of the match off 95 balls with a couple off Morkel on the leg side, in the 46th over.
Having survived a testing spell from the pacers, Laxman seemed much more comfortable against the spin of Harris. He stepped down the wicket to the left-arm spinner and lofted him over the covers for his ninth boundary to take his score to 62.
He was lucky in the next over when his inside edge off Steyn missed the stumps by a few inches and went to the fine leg boundary to take India's lead past 250.
It seems Lady Luck was not being kind on Steyn. The pacer struck Zaheer plumb leg before wicket with a full delivery but Australian umpire Steve Davies ruled in favour of the batsmen suggesting there was inside edge even though replays confirmed there wasn't.
And to rub more salt on South Africa's wounds, Zaheer swept Harris for a boundary through square leg in the next over.
An angry Steyn then struck Zaheer on the helmet with a quick bouncer and soon the two fast bowlers also exchanged a few words.
Laxman was at his elegant best as he timed the ball to perfection. He cut Harris through the point region for yet another four that saw India cross the 200-run mark in the 60th over.
Zaheer and Laxman also brought up the first 50-run partnership of the match in that over as India started building what could be a match-winning total on a pitch still difficult for batting.
Zaheer ended the session in some style when he hit Tsotsobe for two consecutive boundaries through the leg side.
At lunch on Day 3, India held the upperhand as they put up 218 for seven in 62 overs, extending their lead to 292 runs.
Tsotsobe chipped in with useful wickets for figures of three for 43, while Morkel claimed three for 47. Steyn though went for runs as he took one for 60 in 15 overs. Spinner Paul Harris failed to make an impression, giving away 29 runs in ten overs.
Post-lunch session: (80 runs, 21.5 overs, 4 wickets)
India could not consolidate much after the break. They added just ten runs before losing their last three wickets.
South Africa finally ended Zaheer's resistance. The left-armer, who frustrated the hosts as he scored 27 from 63 balls, got an edge off Harris and was caught at second slip.
Zaheer had made a vital contribution with the bat, putting on 70 runs in 117 balls and staying at the wicket for 87 minutes during his eighth-wicket partnership with Laxman.
Ishant Sharma failed to open his account; he lobbed a simple catch to short leg as he looked to negotiate a bouncer from Kallis.
But there was no stopping Laxman, who swept Harris for a boundary through square leg to take his score to 95 and India's lead past 300.
Just when it looked Laxman was set for a well-deserved century, he was caught behind off Steyn for 96. The right-hander, who hit 12 fours in 171 balls during his 280-minute stay at the crease, tried to play the forceful but ended up getting an edge and was snapped by wicketkeeper Boucher.
Despite missing his century, Laxman again proved to be India's saviour. The visitors were bowled out for 228 in 70.5 overs, setting South Africa a stiff 303 to win the Test.
Lonwabo Tsotsobe was South Africa's most successful bowler, claiming three for 43, while Morne Morkel claimed three for 47. Steyn bagged two for 60 to finish with eight wickets in the match. Spinner Paul Harris, however, got just one wicket.
At one stage, India were in dire straits after being reduced to 93 for five, but Laxman guided the team out of trouble, adopting a judicious approach with the tailenders.
South Africa (2nd innings)
Smith was keen to settle scores with his nemesis Zaheer and started off in some style. He drove Zaheer down the ground and then cut a short delivery through point for back-to-back boundaries in the very first over.
In the pacer's next over, he punished him through the leg side for another couple of boundaries and gave his team a flying start.
South Africa's captain was clearly on top as Zaheer was forced out of the attack after just three overs, during which he conceded 24 overs.
Sreesanth also failed to get his rhythm early on as South Africa raced to 53 after ten overs, with both the openers looking to attack at every opportunity.
Harbhajan Singh was brought on in the 12th over and thought he had picked up Petersen's wicket but his huge appeal for leg before wicket was turned down. The right-hander then caused him further grief by charging down the wicket and lifting him over long-on for a boundary.
Against the run of play, South Africa lost a wicket in the final over of the session.
Smith tried to take on a short delivery from Sreesanth but only managed to top edge the pull shot and was caught by Dhoni after a quick 37 from 38 balls, laced with five fours.
At tea, the hosts were 70 for 1 in 13 overs, needing 233 runs for victory with seven sessions still to go in the match. Petersen was unbeaten on 24 from 39 balls, while Hashim Amla was on six.
India were guilty of giving away a lot of boundaries with the new ball, but that wicket lifted their morale right at the end.
Post tea session: (41 runs, 14 overs, 2 wickets)
The wicket of Smith just before the break seemed to have turned the tide in India's favour as they came out with a bang for the final session.
Amla looked in ominous touch as he hit two boundaries off Sreesanth's fifth over but in the very next over the Proteas were dealt a blow.
The extra bounce worked for Harbhajan as Petersen inside edge it to the short leg fielder to be dismissed after scoring 26 from 45 balls.
It got worse for South Africa as Sreesanth claimed the big wicket of Amla in the very next over. The right-hander looked to continue in his attacking mode and went after a wide delivery from Sreesanth only to edge it to wicketkeeper Dhoni after a quick 16.
Harbhajan should have picked up the wicket of Jacques Kallis (0) but Pujara failed to hold on to a difficult chance at short leg.
AB de Villiers was not holding himself back despite the flurry of wickets. He was quick to rock on the backfoot and pulled a short delivery from Harbhajan over midwicket for a six.
Kallis also got his first boundary when he eased a fully wide delivery from Harbhajan through the covers.
Meanwhile, with the light fading it was not long before the umpires decided to call stumps with South Africa on 111 for three in 26 overs with Kallis on 12 and de Villiers on 17.
Despite losing a few wickets, the hosts scored at more than four runs per over but India's bowlers continued to pose threats.
Sreesanth finally showed his true potential as he took two for 30 in seven overs, while Harbhajan claimed one for 29 in eight overs.