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.
