Drew Stanton passed for 283 yards and two touchdowns in his first start of the season for Arizona.
The Cardinals (4-4) bounced back after a bye week from a 33-0 loss to the Los Angeles Rams in London. Starting quarterback Carson Palmer broke his left arm in that loss, and Stanton made his first start since Oct. 6, 2016, when he threw two touchdown passes in a 33-21 victory over the 49ers also at Levi's Stadium.
Stanton completed 23 of 48 passes with one interception.
The 49ers (0-9) remained winless under first-year head coach Kyle Shanahan.
Rookie quarterback C.J. Beathard completed 15 of 30 passes for 201 yards with one interception and ran for a touchdown in his third career start for the 49ers. Quarterback Jimmy Garoppolo, who was acquired by San Francisco on Oct. 30 from New England in a trade, suited up as Beathard's backup, but did not play.
The 49ers opened the second half with a 13-play, 75-yard touchdown drive capped by Beathard's 1-yard run to cut Arizona's lead to 14-10 with 9:43 left in the third quarter.
Phil Dawson kicked a 25-yard field goal with 13:31 left in the game, extending Arizona's lead to 17-10. The Cardinals drove 39 yards in 11 plays and used 7:02 for Dawson's 32-yarder with 5:33 left, making it 20-10.
Linebacker Karlos Dansby sealed the victory with an interception at Arizona's 7 with 2:28 left to play.
Peterson, who came to Arizona in a trade from New Orleans on Oct. 10, rushed for 79 yards on 17 carries in the first half when Stanton threw two touchdown passes and the Cardinals built a 14-3 lead.
Arizona capitalized on a 49ers turnover to strike first. Cardinals safety Tyrann Mathieu stripped the ball from fullback Kyle Juszczyk after a 7-yard catch, and cornerback Patrick Peterson recovered and returned it 47 yards to the 49ers' 6.
Three plays later, Stanton scrambled to his right and hit wide receiver Jaron Brown in the end zone, giving Arizona a 7-0 lead with 10:15 left in the first quarter.
San Francisco cut Arizona's lead to 7-3 on Robbie Gould's 42-yard field goal with 14:55 left in the first half.
The Cardinals answered with a 75-yard touchdown drive capped by Stanton's 11-yard touchdown pass to tight end Jermaine Gresham, who beat rookie cornerback Ahkello Witherspoon on a slant to make it 14-3 with 11:04 remaining.
Arizona had a chance to score again late in the first half, but on second-and-10 from the San Francisco 14, safety Eric Reid intercepted Stanton's pass intended for Gresham in the end zone.
NOTES: 49ers starting FS Jaquiski Tartt suffered a wrist injury in the second quarter and did not return. ... 49ers WR Trent Taylor (rib) and linebacker Elijah Lee (knee) were hurt in the second quarter and did not return. TE Cole Hikutini suffered a knee injury in the first quarter and did not return. FB Kyle Juszczyk injured his neck in the third quarter and did not return. ... Arizona DL Frostee Rucker and LB Haason Reddick and 49ers RB Carlos Hyde were ejected with 3:29 left to play for fighting. The fight erupted after Cardinals S Antoine Bethea's late hit on 49ers QB C.J. Beathard.