GLENDALE, Ariz. (AP) -- John Skelton earned redemption in a rematch with San Francisco. The Arizona defense and a spectacular show by Larry Fitzgerald made it possible.
Skelton stepped in for the injured Kevin Kolb and threw for 282 yards and three touchdowns, and the Cardinals rallied to hand the 49ers their third loss of the season, 21-19, on Sunday.
Fitzgerald had seven catches for 149 yards, including a 46-yarder for a touchdown and a 53-yarder to set up the go-ahead score. He also had a vicious block that helped free Early Doucet on a 60-yard touchdown reception.
" That's Fitz being Fitz," Skelton said.
Arizona (6-7) has won five of six after a six-game losing streak left them 1-6.
" You guys stuck a fork in us quite a while ago,'' coach Ken Whisenhunt told reporters after the game. " I think our guys never let it get to them. How many times during those first weeks did we say that we were going to stay the course and that it was going to turn for us? We believed it."
Kolb left the game after a blow to the head on Arizona's third play. Skelton, benched after throwing three interceptions in the Cardinals' 23-7 loss at San Francisco on Nov. 20, had a 60-yard TD pass to Doucet and a 3-yard toss to Andre Roberts for what proved to be the winning score early in the fourth quarter.
" You're only as good as your last play, your last game,'' Skelton said. " You kind have to live with that until you get another opportunity. You never know when that opportunity is. You've just got to be ready and make the most of it."
Skelton was able to overcome two interceptions and a lost fumble in this one.
Arizona sacked Alex Smith five times after getting five against Dallas in its 19-13 overtime win over the Cowboys a week earlier. The 49ers (10-3) were at the Cardinals 4-yard line twice and the 6 once in the second quarter and had to settle for short field goals by David Akers each time.
Frank Gore rushed for 72 yards on 10 carries for the NFC West champion 49ers (10-3), including a 37-yard touchdown run that put San Francisco ahead 19-7 early in the second half. He passed 1,000 yards rushing for the fifth time in his career, but didn't do much damage after that.
Smith completed 18 of 37 for 175 yards and no TDs. He lamented the missed opportunities in the second quarter and the failure to get close enough for a game-winning field goal at the end.
" We have to be honest with ourselves when we look at the film,'' Smith said. " It is not something we can just dismiss and move on."
The 49ers were without standout inside linebacker Patrick Willis , who missed the second game of his career, because of a right hamstring injury.
On Arizona's possession following Gore's big run, Fitzgerald went over the middle and outjumped safety Dashon Goldson for the ball, then ran the remaining 20 yards for the score to cut the lead to 19-14 with 9:04 left in the third quarter.
On the play, Fitzgerald passed 1,000 yards for the season for the sixth time in his eight years in the NFL, the last five in a row.
Then on the first play of the fourth quarter, Fitzgerald took a pass over the middle and ran to the San Francisco 20, a 53-yard play. On third-and-2 from the 12, Skelton threw a screen pass to Doucet for a 9-yard gain to the 3. Skelton threw to Roberts on the next play, and the receiver crossed the goal line for the touchdown that gave the Cardinals the lead, 21-19, with 11:50 remaining.
Kolb, in his second start after missing four games with a right turf toe and bruise on the side of his same foot, was hurt when he faded to pass and was hit by Justin Smith as he threw. It was one of two forced fumbles and two sacks for Smith.
San Francisco got the ball on its 43 and, in an 11-play drive that managed 15 yards thanks to three sacks and a couple of penalties, Akers' 46-yard field goal made it 3-0.
San Francisco pinned Arizona deep again, and Ted Ginn Jr.'s 52-yard punt return put the 49ers on the Cardinals 4. But Arizona's defense, strong all day, held and Akers' 22-yarder put the 49ers ahead 6-0 with 14:02 left in the half.
Then came the oddest moments of the afternoon.
On third-and-7, Skelton scrambled for a first down but, on a hit by Smith, fumbled the ball and San Francisco recovered at its 47. The 49ers moved to the Arizona 40, where Akers lined up for a 50-yard field goal attempt. But it was a fake, with holder Andy Lee tossing to backup center Jonathan Goodwin , lined up as a tight end, for the apparent score.
The whistle blew mid-play, though, with Arizona challenging the previous play, a pass from Alex Smith to Kyle Williams . But the replay system wasn't working, and the play was repeated. This time, Akers' 50-yard attempt was wide right, his first miss from 50 and beyond in seven tries this season.
The next play, Skelton threw over the middle to Doucet, and with the help of Fitzgerald's block, he raced 60 yards for the score and Arizona led 7-6 with 7:10 left in the half.
" It ended up being a 14-point swing when you look at it,'' San Francisco coach Jim Harbaugh said. " What the officials said was they challenged the play before we faked the field goal."
The 49ers responded with a 10-play, 69-yard drive, but again stalled deep in Arizona territory. Akers' 27-yard field goal put the 49ers back on top 9-7 with 1:58 to play.
Notes: Fitzgerald is the eighth player in NFL history to top 1,000 yards receiving in six of his first eight seasons. ... For the second week in a row, all five Arizona sacks were by different players. ... Goldson left the game with a hip injury on the play Fitzgerald scored. ... San Francisco lost starting left Joe Staley in the first quarter with a head injury.