The Niners' running game came to the fore in the second half, taking the lead for the first time with 7:54 remaining in the fourth quarter after Christian McCaffrey's touchdown.
San Francisco went 12-0 in the second half, turning around a 16-10 half-time deficit, ending the Chargers' five-game win streak against them. San Francisco claimed back-to-back victories with the win to improve to 5-4, while the Chargers dip to 5-4 having lost two of their past three games.
The Niners enjoyed more possession, rushing for 157 yards compared to the Chargers' 51, with Elijah Mitchell (89 yards on 18 carries) and Deebo Samuel (27 yards on four carries) contributing well on their returns from injury.
Niners quarterback Jimmy Garoppolo completed 15 of 23 passes for 197 yards with no touchdowns or interceptions, although he ran in a TD late in the first half.
Garoppolo linked up with Brandon Aiyuk, who had six receptions for 84 yards, on a 24-yard pass leading to McCaffrey's decisive rushing two-yard TD.
In the final two minutes, a one-handed Josh Palmer could not reel in a desperate fourth-down pass from Herbert, who finished the game on 21-of-35 passing for 196 yards with one TD and one interception, before Robbie Gould made it a six-point game with a 20-yard field goal.