It’s so that you can write functions that for instance take both a set and frozenset, then just call .copy() and have it still work. There’s a couple of these “useless” functions here and there. Another example is int.is_integer(), which matches float.is_integer().
While there’s no reasonable use case to create a copy of a frozenset, the existence of frozenset.copy provides an interface for a frozenset subclass, where creating a copy may actually make sense.
Note that this outputs False as intended:
class S(frozenset):
pass
A = S([0, 1, 2])
B = A.copy()
print(A is B)