Anya Shrubsole hit the winning runs off the first ball she faced, with the hosts needing two runs from the final three balls of the innings.
In a tight encounter at Bristol, South Africa scored 218 for six off their 50 overs, with Mignon du Preez top scoring with an unbeaten 76 off 95 balls.
England were in sight of victory but lost two wickets for four runs in nine balls before Shrubsole's first-ball boundary sealed a place in Sunday's final at a sold-out Lord's against either holders Australia or India, who meet on Thursday.
News that makes sense
Your trusted source for staying up-to-date with the world around you. Get free daily news updates and analysis, straight to your inbox.
(Reporting by Neville Dalton; Editing by Christian Radnedge)
