hanip.me

Privacy Policy

A plain account of the data hanip.me actually handles.

Effective September 11, 2026

hanip.me has no sign-up and no login. Here's every piece of data this service actually stores or sends.

What stays on this device only

The foods you met through cards and your choice and execution records, the food paths you explicitly chose and their outcomes, meal and reopen state, the last shuffle method, captions already seen, install-banner dismissal, a random install ID, your explicit answer about whether a prior bite was actually eaten, food-level recommendation exclusions, and the bites you kept in the Dex live in your browser's local storage. To choose the home-screen cat's reaction, we also store the visit count, last-visit timestamp, last reaction context, and illustration variant number. The raw home-reaction record, exact visit count, and last-visit timestamp are not sent as product analytics or in a separate API payload. However, the static-file request path used to load the selected cat image contains the reaction context, illustration variant number, and lantern stage, so the hosting/CDN layer may see that path as request information. For the same reason, a title share link (/t/{title id}) carries the title id you chose to send, plus a menu id only when you send one, and nothing else. Home-reaction values can be cleared under Data management, but they are excluded from backup export and import. To handle imported backups safely even before progressive recommendations are enabled, recommendation progress may contain only discovered, chosen, and executed food IDs; activity days and counts; recently shown foods and recent explicit rejections; preference weights and exclusion tags; novelty tolerance; policy and Core versions; and two bounded sets of random execution receipts used to avoid counting one execution twice—up to 256 for interrupted-action recovery and up to 1,000 aligned with the device's 1,000-entry event log. Only when all three “None of these” signals and all three food records are saved do we also store a correction record containing those three food IDs, the meal slot and date, and whether its one-time adjustment was used. To prevent that one-time adjustment from being duplicated across tabs or after an interruption, we also store random receipt and temporary claim identifiers with an expiry of no more than two minutes; the exact adjusted three-card session retains the same identifiers as completion proof. It first avoids them once in the next matching meal slot, then uses only an ordering adjustment that fades for up to 14 days. Choosing one of those foods or explicitly opening its map or delivery option removes that food from the adjustment immediately. Choice and execution events also keep, locally, only the correction-receipt generation seen when the action began, so a late old action cannot clear a newer correction. Immediately before leaving for a map or delivery app, that tab keeps the executed food ID, a random intent ID, its creation time, the same data-generation value, and that correction-receipt generation when present in session storage and treats it as recoverable for no more than 30 minutes. It is removed as soon as the write succeeds; an expired or malformed value is removed when hanip.me checks it after your return; and closing the tab also removes it. This temporary data is excluded from backup export and import; Data management or clearing browser site data removes it. At request time only, choices stored on this device are weakly linked to reviewed taste classifications to adjust future recommendation order, and an explicitly excluded food is also removed from that calculation. A map or delivery action for the same chosen food may corroborate the choice, but execution alone never creates a new taste preference or proves eating or satisfaction; the one-meal challenge choice is not stored.

Exact food-linked answers and recommendation exclusion lists stay in this browser and are used only to tailor recommendations and fill the record, dex, and profile screens. To measure whether the feature works, we send only an unlinked coarse event type such as prompt shown, ate, did not eat, excluded, or restored. Metrics never include a food ID or name, meal slot, raw answer, exclusion list, rejection reason, exclusion tag, or preference weight. The raw install ID is not sent either, but for pseudonymous visit statistics we SHA-256 hash it and send only the first 16 bytes (32 hexadecimal characters) as a pseudonymous installation digest.

To stop delayed writes from an older screen from reappearing while records are cleared or imported, the browser also keeps one internal mutation-generation number containing no content, user, or time data. It is never exported and is advanced when records are cleared or imported. Clearing this site's browser data removes it too. On older browsers without Web Locks coordination, basic records remain available in one tab, but simultaneous writes from multiple tabs can lose an update. Record clearing and importing fail without making a partial change in that environment.

Under Data management in Service info, you can export or import choice and recommendation records and saved location, and clear all device records—including home-reaction values—and saved location. Clearing site data in your browser removes them too.

What we collect as product analytics — pseudonymous visit statistics

To improve the product, we tally sixteen (16) event types: visit, start, reveal, decide, share, execute, result_view (a shared-result landing only), recommendation_reason_impression, recommendation_reason_expand, recommendation_reason_collapse, feedback_prompt, feedback_tasted, feedback_not_eaten, feedback_exclude, feedback_exclude_undo, and dex_view (whether the dex screen was opened, counted once per visit). The browser sends a pseudonymous installation digest made by SHA-256 hashing the raw install ID and taking the first 16 bytes; a random per-visit ID; the event type; a visit-local sequence from 0 through 14 that carries no exact time; one of ten source categories (cat, threads, food-guide, intent-landing, direct, other, theme, room, search, or pwa); the one interface language shown when the visit began (ko, en, or ja); only for decide events, a rough duration bucket; the app version; and, only when a reviewed experiment is active, one closed-code experiment_id and variant pair captured for the whole visit. The two experiment values are not stored during the current baseline. The ten source categories mean: cat, arrived from a Hanip Cat post link; threads, from a Threads link; food-guide, from a food guide's card CTA; intent-landing, from an intent landing CTA; theme, from a theme page's card CTA; room, from a friends' help room link; search, from a search engine (we read only the referrer's host, never the address itself); pwa, opened from the app added to your home screen; direct, any other direct visit; and other, a marker we did not recognize. To tell search and pwa apart, the browser alone reads the host of document.referrer and the display mode (standalone); once that single source value is chosen, neither the referrer address nor the display mode is sent to the server or stored. At receipt, the server stores the KST calendar date, derives the measurement context (production or qa) from the request address, and retains the app version and event sequence together only when the request exactly matches the current server build; sequences from older or unrecognized versions are not stored. Experiment values are normalized to a registered pair. An interface language we do not recognize, or a request that sends none (for example an older browser), is also left empty rather than guessed as a language. For production requests, the server also derives one low-cardinality traffic class—external, owner_test, or synthetic—from a request cookie so owner review and controlled canary traffic can be excluded from the official external baseline. The cookie is a best-effort exclusion marker, not proof of authority or a human visitor, and its raw value is not stored in the metrics table. To see only whether a visit came from Korea, the server also folds the country information already attached to the request into exactly one of two values, KR or other, and stores nothing finer: no city, region, coordinates, or the country code it was folded from. A request whose country is unknown is left empty rather than guessed as other. This value has nothing to do with your browser location permission or the location you may have saved for 'Find nearby restaurants'. A device date sent by an older browser is ignored. Each type is counted at most once per visit. When an exactly matching event request passes validation and rate limits and reaches the D1 upsert, the server keeps one row and stores only a lower bound of attempts observed at that boundary, capped from 1 through 2. This is not a count of every server arrival or specifically of automatic retries. Reading a food guide or an intent landing creates no event. We use food-guide after the guide CTA and intent-landing after an intent landing CTA. These public markers are best-effort analytics, not authenticated proof of origin.

We do not send an exact guide or intent-landing URL or an individual page identifier. An explicit entry link sends only one of discover, decide, or collect (exploring food, choosing a meal, or collecting), separately from the source category. We capture it once when the visit starts and keep it unchanged during language changes and retries. Missing or unrecognized markers stay empty rather than being inferred. This grouping does not measure public landing impressions or exits, order-card saves, actual orders, or meals eaten. Two reviewed intent landings are currently public — spicy food and K-Trends — so intent-landing alone does not identify which page's CTA was used. App version, measurement context, and experiment codes are low-cardinality deployment and comparison labels, not menu or copy content. The metrics otherwise never include which food it was, a food ID or name, search query, meal slot, raw answer, exclusion list, card position, an individual location such as a city, region, or coordinates, recommendation factors, exact timestamps, your name, or your email. Opening an explanation never becomes a taste signal. We keep metrics for 30 KST calendar days using the server-assigned KST date and automatically delete older rows every day.

How weather is used

To match the card background (clear, cloudy, rain, snow) and gently adjust reviewed warm-soup, light-food, and rainy-day classifications to today's weather, we briefly use the rough, city-level location attached to the request only to check the weather at that moment.

We don't use precise GPS coordinates, and Hanip does not write latitude or longitude to its response, storage, or operational logs. The weather lookup sends rough coordinates to Open-Meteo, while Hanip reuses only the weather result for the same coarse area for about 15 minutes.

Weather can affect ordering only among foods that already passed review and eligibility, within a bounded 0.90–1.15 multiplier. It never relaxes exclusions, allergy boundaries, meal eligibility, or Challenge gates, and we do not store city, temperature, weather kind, or observation time in recommendation records or metrics. When weather actually contributes to an ordering, only that generic fact and its numeric contribution may remain in the recommendation session on this device. Boknal, Valentine's Day, and Black Day cues use only the KST date and reviewed public references; they do not change recommendation scores or taste records.

Offline caching and home-screen install

hanip.me is a PWA, so it caches static assets like screens and images on your device to make the next visit faster. The cache stays on this device only, and API responses (like your visit history) are never cached.

Installing to your home screen doesn't create any new data — it's just a shortcut that opens the browser faster.

Friend help-room (voting) data

The 'help room' feature shows friends three menu candidates and asks them to vote. To operate a room, the separate rooms server briefly stores the 3 card ids selected when the room was created, friends' pseudonymous votes, and the reason tag attached to each vote; the room-creation request also sends the main app's numeric app version. It never asks for a name, Kakao account, phone number, or precise location, and both the value that tells voters apart and the room owner's authority value are stored as one-way hashes, never in plain text. To avoid counting the same room's “View my three cards” handoff twice, this tab's session storage keeps at most 16 pending-or-shown room scopes as 16-character values instead of raw roomIds, only until the tab closes. Data management also removes them.

This room-operation data is automatically and completely deleted by its original alarm, at most 15 minutes after creation. If the room owner finalizes a menu earlier, votes and reason tags are not deleted immediately and may remain until that alarm.

Pseudonymous room-level metrics and operational records remain afterward. They may contain a room_hash made by SHA-256 hashing the public share-link roomId without a separate secret key; the KST calendar date; meal slot; candidate and final menu ids; room-created, first-vote, finalized, expired, and eleven host or guest screen-action event types; the per-menu vote-count snapshot and participant count at each event; final rank, tie state, and duration buckets; the measurement context (production or qa) derived by the server from the request origin; and the format-checked numeric app version sent by the client. Differences between successive vote-count snapshots for the same room_hash may reveal which card received or changed a vote, but the value that distinguishes a voter and individual reason tags are not included in these long-term records. Public request-origin and app-version markers are best-effort comparison labels, not authenticated proof of origin or version. These pseudonymous records currently have no automatic deletion deadline.

What we don't do, and hosting security

No sign-up, no login. Each time you choose 'Find nearby restaurants,' the browser checks your current location and applies any location permission decision you already made. If allowed, coordinates are reduced to three decimals (roughly 100 m) and stored with a broad accuracy bucket and last-saved date, linked to the same pseudonymous installation digest used for metrics. We use this only for nearby restaurant search and saved-location management. Every day we automatically delete each location on the KST calendar date 180 days after its last save, and you can also delete yours anytime under Data management in Service info. We don't run ads or tracking scripts, and never sell data or share it for advertising.

We use Cloudflare's security layer for hosting and malicious-traffic protection. Cloudflare may set the __cf_bm bot-detection cookie and process request IP and browser information for security. hanip does not use that cookie for advertising or menu personalization.

These execution links are designed for use in Korea. 'Find nearby restaurants' opens a Naver Map search URL with the menu name and the approximate coordinates just checked. If you choose 'Search by dish name only,' hanip.me does not check or store your current location and sends only the menu name, without coordinates. 'Find in a delivery app' copies the menu name on your device and opens the installed Baemin or Coupang Eats app. Each provider's privacy policy and terms apply after you leave hanip.me.

About this service

This is a personal project, run by one person. Under Data management in Service info, you can export choice and recommendation records and saved location, and clear all device records—including home-reaction values—and saved location. Please report bugs or accessibility problems through the email link below.

Contact us by email

We only use the email you send to reply to you.