The perfect tense in Dutch uses either hebben (to have) or zijn (to be) as auxiliary. The choice is not arbitrary. Zijn is used with: (1) verbs of motion that imply a change of location — gaan (gegaan), komen (gekomen), rijden (gereden — when destination is explicit), vliegen (gevlogen), lopen (gelopen — when destination matters), fietsen (gefietst — with destination); (2) verbs of change of state — worden (geworden), groeien (gegroeid), sterven (gestorven), veranderen (veranderd — with zijn); (3) specific verbs: zijn (geweest), blijven (gebleven), slagen (geslaagd), lukken (gelukt), mislukken (mislukt), schrikken (geschrokken), vallen (gevallen).
Hebben is used with: all transitive verbs (verbs with a direct object), most verbs that do not imply location change, and reflexive verbs. Ik heb gegeten (I have eaten — transitive). Ik heb gewerkt (I have worked — no change of location). Hij heeft zich gewassen (He has washed himself — reflexive). When the same verb can be used with or without a direct object, the auxiliary changes: Ik heb de auto gereden (I drove the car — transitive, hebben) vs Ik ben naar Amsterdam gereden (I drove to Amsterdam — change of location, zijn).
The most reliable test: does the sentence describe movement to a new place or a change of state? If yes, try zijn. If there is a direct object, use hebben. When in doubt: hebben is the default for most verbs. The verbs that take zijn are a learnable finite list — memorise the most common ones (gaan, komen, blijven, zijn, worden, vallen, slagen, groeien, sterven) and apply hebben to everything else until you encounter evidence otherwise.