After a wedding, a conference or a race, the photographer delivers 2,000 photos and every guest asks: which ones am I in? A face search fixes it. The guest takes one selfie, and the gallery shows only the photos that contain them.
Below is the full flow in Python, with real results from a live 18-photo birthday gallery.
Want to try it on your own gallery? Get a key for the Face Analyzer API and point the script at a folder of event photos.
How it works
- Index the gallery once. Each event photo goes to a face repository. Every face in it is stored, labeled with the photo's file name.
- Search with a selfie. Each match carries the label of the photo it came from, a similarity score and the face's position.
A group photo with five people produces five stored faces with the same label. The label turns a face match into a photo match.
Step 1: one repository per event
import os
import requests
from concurrent.futures import ThreadPoolExecutor
BASE = "https://faceanalyzer-ai.p.rapidapi.com"
HEADERS = {
"x-rapidapi-host": "faceanalyzer-ai.p.rapidapi.com",
"x-rapidapi-key": "YOUR_API_KEY",
}
EVENT = "birthday-2026-10-17"
requests.post(
f"{BASE}/create-facial-repository",
headers=HEADERS,
data={"repository_id": EVENT},
)
Step 2: index every event photo
def index_photo(path):
"""Save every face in one event photo, labeled with the photo's file name."""
with open(path, "rb") as f:
r = requests.post(
f"{BASE}/save-face-in-repository",
headers=HEADERS,
files={"image": f},
data={
"repository_id": EVENT,
"external_id": os.path.basename(path),
"max_faces": "20",
},
)
return os.path.basename(path), len(r.json()["body"].get("FacesId", []))
photos = sorted(os.path.join("event_photos", n) for n in os.listdir("event_photos"))
with ThreadPoolExecutor(max_workers=4) as pool:
for name, faces in pool.map(index_photo, photos):
print(name, faces, "faces indexed")
18 photos, 76 faces, one call per photo.
Step 3: find a guest's photos
MIN_SIMILARITY = 95
def find_my_photos(selfie_path):
"""Return the event photos that contain the person in the selfie."""
with open(selfie_path, "rb") as f:
r = requests.post(
f"{BASE}/search-face-in-repository",
headers=HEADERS,
files={"image": f},
data={"repository_id": EVENT},
)
body = r.json()["body"]
if "error" in body:
return None # no face found in the selfie: ask for a new one
best = {}
for m in body["FaceMatches"]:
photo = m["ExternalImageId"]
if m["Similarity"] >= MIN_SIMILARITY and (
photo not in best or m["Similarity"] > best[photo]["Similarity"]
):
best[photo] = m
return sorted(best.values(), key=lambda m: m["Similarity"], reverse=True)
matches = find_my_photos("selfie.jpg")
print(len(matches), "photos found")
14 photos found
IMG_7336946.jpg 100.0
IMG_7337110.jpg 99.99
...
IMG_7336992.jpg 98.89
She appears in exactly those 14 photos, and the 4 left out are the ones she is not in. Five-person group shots, a side view and a face cut by the frame edge all matched. The search took about half a second.
Edge cases: a selfie with no face returns an error in the body (handled above), and a person who was not at the event gets an empty FaceMatches list.
Step 4: highlight the guest
from PIL import Image, ImageDraw
def highlight(photo_path, match, out_path):
"""Draw a box around the guest's face in one matched photo."""
im = Image.open(photo_path).convert("RGB")
w, h = im.size
box = match["BoundingBox"]
rect = [
box["topLeft"]["x"] * w, box["topLeft"]["y"] * h,
box["bottomRight"]["x"] * w, box["bottomRight"]["y"] * h,
]
ImageDraw.Draw(im).rectangle(rect, outline=(52, 211, 153), width=6)
im.save(out_path)
The whole script (create, index 18 photos, search, highlight 14) ran in under 8 seconds.
Production tips
- Ask for a clear, front-facing selfie
- Show guests only their own matches
- Get consent before the selfie, do not store it, and call
/delete-facial-repositorywhen the gallery closes - Index new uploads as the photographer delivers them
- Genuine matches scored 98.89 and above, so a 95 cutoff keeps a wide margin
More on the full guide at ai-engine.net, including where selfie search fits (photographers, races, weddings, conferences, schools).
Sources: GDPR Article 9 (biometric data), test photos by Polina Tankilevitch on Pexels.
👉 Grab a key from the Face Analyzer API page and run a search with your own selfie.

Top comments (0)