`ST_Contains`/`contains` is slow when used row-by-row without a spatial index. Use a geopandas or postgis, and make sure both layers share the same CRS/SRID
import geopandas as gpd
points = points.to_crs(polygons.crs)
result = gpd.sjoin(points, polygons, how="left", predicate="within")