Let's count? I am including pokemon such as Charmander, Chimchar, etc, which joined Ash of their own will without a battle as "CAUGHT".
List of Ash's Pokemon:
Kanto and Orange Islands
- Pikachu - Given. Not caught.
- Caterpie - Caught. Released as a Butterfree.
- Pidgeotto - Caught. Left in the wild as a Pidgeot
- Bulbasaur - Caught.
- Charmander - Caught. Joined Ash of his own will. Left to train. Rejoined and with Oak now.
- Squirtle - Caught. Released back to the Squirtle Squad.
- Krabby- Caught. With Prof. Oak as a Kingler
- Raticate - Traded for Butterfree. Got back
- Haunter - Joined Ash for fun. Left for Sabrina.
- Primeape - Caught. Left for Fighting trainer.
- Muk - Caught in the power plant.
- Tauros - Caught in Safari Zone.
- Lapras - Caught. Released with family.
- Snorlax - Caught on Orange Island.
Johto
- Heracross - Caught.
- Chikorita - Caught. With Oak as a Bayleef
- Cyndaquil - Caught. With Oak as a Quilava
- Totodile - Caught
- Shiny Noctowl - Caught
- Beedrill - Caught in Bug Catching Contest. Released to Casey.
- Phanpy - Hatched.. With Oak as a Donphan
- Larvitar - Hatched. Released
Hoenn and Battle Frontier
- Tailow - Caught. With Oak as a Swellow
- Treecko - Caught. With Oak as Sceptile
- Corphish - Caught
- Torkoal - Caught
- Snorunt - Caught. With Oak as a Glalie
- Aipom - Caught. Traded to Dawn
Sinnoh
- Starly - Caught. With Oak as a Staraptor
- Turtwig - Caught. With Oak as a Torterra
- Chimchar - Caught. With Oak as an Infernape. Left Paul to join Ash, like Charmander
- Buizel - Traded. From Dawn
- Gligar - Caught. With Oak as a Gliscor
- Gible - Caught
Unova
- Pidove - Caught. With Oak as a Unfezant
- Sewaddle - Caught. With Oak as a Leavanny
- Roggenrola - Caught. With Oak as a Boldore
- Palpitoad - Caught. With Oak
- Scraggy- Hatched. With Oak
- Oshawott - Given by Juniper. With Oak
- Tepig - Another fire starter left by a trainer. Caught. With Oak as a Pignite.
- Snivy - Caught! With Oak
- Krokorok - Caught. With Oak as a Krookodile
Kalos
- Froakie - Caught. Released. With Squishy and Z2
- Fletchling - Caught. With Oak as a Talonflame
- Goomy - Caught. Left in the Wetlands
- Noibat - Hatched. With Oak as a Noivern
- Hawlucha - Caught. With Oak
Alola
- Rowlet - Caught! Ash has caught his first pokemon in Alola.
- Rockruff - Caught! In Alola as Lycanroc
- Litten - Caught! in Alola as Incineroar.
- Poipole - Caught! In ultra space. Came back as Naganadel for Pokémon league
- Meltan. Caught! In Alola as Melmetal.
Galar
- Dragonite - Caught! With Ash in various regions.
- Gengar - Caught! With Ash in various regions
- Riolu - Hatched! Given to Ash by Nurse Joy.
- Farfetch’d - Caught! With Ash in various regions:
Tl;Dr Ash has got 57 unique pokemon species. He got 2 (Pikachu, Oshawott), Traded for 2 (Raticate, Buizel), hatched 5 (Larvitar, Phanpy, Scraggy, Noibat, and Riolu). Also, Haunter just traveled with him so not counted as catching.
Thus Ash has CAUGHT [57-(2+2+5+1) = ]47 unique species.
Edit: As requested by OP removed a quote referencing the number of pokemon dexed by Ash. Dexed pokemon are a larger set of pokemon, which include hatched, evolved, and owned in any other way (Gift/Trade, etc.).
Also, couldn't resist.