South Africa were cruising through in the first two sessions but West Indies came up with a much improved show after tea, picking up five wickets.
Opener Aiden Markram continued his rich vein of form falling four runs short of what could have been his second successive Test hundred.
Heinrich Klaasen will resume on Thursday unbeaten on 17 with Keshav Maharaj, who has yet to face a ball.
South Africa won the toss and elected to bat, reaching 247 for two at tea with Dean Elgar out for 42 and Markram scored a fluent 96 in which he struck 17 fours.
He attempted a sweep off impressive West Indies spinner Gudakesh Motie (3-75) but could only toe-end the ball to Jermaine Blackwood, who had run around from slip and juggled his catch but held on.
“We felt the pitch played nicely and quickened up after lunch. We couldn’t really capitalise, but hopefully we can get more runs in the morning,” Markram told reporters.
“We want to play a nice, attacking brand but it is still test cricket and you need to find the right balance. (My shot to get out) was a bit of a brain-fade.”
The visitors were wild with their line and length for the first 60 overs and paid the price, but tightened up in the evening session on a wicket with pace and bounce.
Home captain Temba Bavuma made 28 after his pair of ducks in the first test before he was trapped leg before wicket not offering a shot to Jason Holder.
Tony de Zorzi, playing in his second test, compiled a maiden half-century with a neat 85 before Motie found a way through his defences and he was bowled.
Recalled left-hander Ryan Rickelton played some excellent shots but was caught by wicketkeeper Joshua Da Silva off seamer Alzarri Joseph flashing at a wide ball with his score on 22.
Wiaan Mulder was out for 12, bowled by Kyle Mayers with an in-swinging length ball, while Simon Harmer edged the latter to Da Silva when he had 1.
South Africa won the first Test in Pretoria by 87 runs.
(With Reuters Inputs)