The West Indian attack responded brilliantly to captain Darren Sammy’s decision to bowl first on a slow pitch offering help as they restricted South Africa to 122 for eight.
Johnson Charles hit 32 at the top of the order as the 2012 champions seemed in control of their run chase until leg-spinner Imran Tahir struck twice in consecutive deliveries in his last over to haul his side back into the game.
Marlon Samuels, named man of the match for his 44, was then removed by paceman Chris Morris in the penultimate over.
Carlos Brathwaite calmed West Indian jitters, however, when he hit a six off paceman Kagiso Rabada as West Indies clinched a third successive victory, with two balls to spare.
“I was smiling … but inside there were some butterflies,” Sammy said. “We came here to win this match to qualify and we have done that so I am very happy.”
Earlier, opener Quinton de Kock (47) played a disciplined innings to rescue South Africa after they slumped to 47 for five in the ninth over.
De Kock added 50 for the sixth wicket with David Wiese (28) to give his team a competitive total to defend.
“It felt like all game we were just behind West Indies and trying to catch up,” said South Africa skipper Faf Du Plessis. “It was a 135 pitch but it was a great fight by the boys.
“This game makes us all very old very quickly. West Indies were just a little bit better than us today.”
Chris Gayle, Andre Russell and Dwayne Bravo picked up two wickets apiece for West Indies who retained the same side that beat Sri Lanka in their last match in Bangalore.
South Africa, who have never lifted the trophy but were one of the pre-tournament favourites, have two points from three Group One games and look like going out.
Second-placed England have four points and can claim a spot in the last four with a win on Saturday over Sri Lanka who are also on two points. Afghanistan are bottom with no points.