Like other projectiles, arrows use a player's bounding box instead of their hitboxes for collision detection.
Upon intersecting with a player's bounding box, the game tries to attach the arrow to the player model. It tries to figure out which body part it should be attached to.
A raytrace is performed using the arrow's position and velocity at the point of impact, and when it intersects with a hitbox then the arrow is attached to that.
Otherwise, the game loops through all of the player's hitboxes. For each of them, a raytrace is performed from the arrow to their centre, getting the distance until intersection. The arrow is attached to the one with the shortest resulting distance.
If the arrow is attached to the head hitbox, then it's considered a headshot.