Quinton de Kock and Rassie van der Dussen had frustrated England for 44 overs with a sixth wicket stand. However, Stokes provided late drama with 8.2 overs remaining to level the four-match series ahead of the third Test starting in Port Elizabeth on January 16.
The win will be especially pleasing for the way England stuck to their task on a flat fifth-day wicket, with Stokes’ superb late burst providing figures of 3-35.
Chasing a Test record 438 to win, those thoughts did not last long, but South Africa looked relatively comfortable as they reached 237 for five with 26 overs remaining in the match.
However, for the second time in the innings a key man gave his wicket away. De Kock (50) attempted to pull a dragged down delivery from part-time leg spinner Joe Denly, but succeeded only in picking out Zak Crawley at mid-wicket.
It was an unnecessary stroke that opened the door for England and when seamer Stuart Broad removed the obdurate Van der Dussen (17 from 140 balls), it was well and truly ajar.
It was a fine bit of captaincy by Joe Root, who placed James Anderson at leg slip for the ball and Van der Dussen duly picked him out.
Stokes removed Dwaine Pretorius and Anrich Nortje in successive balls, both caught at slip, and claimed the victory in front of an ecstatic Barmy Army when Vernon Philander was the last man out, caught by Ollie Pope.
South Africa had given themselves a chance with some stern resistance, not least from debutant opener Pieter Malan, who batted for 288 balls for his score of 84.
But England looked on course for victory at lunch after grabbing the key wicket of South Africa captain Faf du Plessis (19), who will be disappointed with his shot selection as he tried to take on spinner Dom Bess with a powerful sweep, but succeeded only in picking out Denly at square leg.
De Kock and Van der Dussen put up a defensive wall, but eventually England broke through to claim a hugely satisfying win.
South Africa won the first Test in Pretoria by 107 runs.