{
  "data": {
    "id": "AJWGw6hpbjxZtYxx5",
    "actId": "OnjT5Guhg9dgP9PKv",
    "userId": "zq8lKbpLzTjGDayPC",
    "startedAt": "2026-11-07T15:36:17.421Z",
    "finishedAt": "2026-11-07T15:36:21.155Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 3667,
      "runTimeSecs": 3.667,
      "computeUnits": 0.004074444444444445,
      "imageSizeBytes": 319064064
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "GK9YjZRyQZVzOdoH5",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"Snapchat Snap Map Scraper\",\n  \"description\": \"Collect Snap Map places, live public snaps and 7x24 popularity data from Snapchat's public web pages. Search by place keyword, look up specific places, or browse US cities and categories. No Snapchat account, cookies or proxy setup required.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"mode\": {\n      \"title\": \"Mode\",\n      \"type\": \"string\",\n      \"description\": \"Choose what to scrape: search Snap Map places by keyword, look up specific place URLs or IDs, or browse US cities and categories.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"searchPlaces\",\n        \"placeDetails\",\n        \"browseLocal\"\n      ],\n      \"enumTitles\": [\n        \"Search places by keyword\",\n        \"Get details for specific places\",\n        \"Browse US cities and categories\"\n      ],\n      \"default\": \"searchPlaces\",\n      \"prefill\": \"searchPlaces\",\n      \"sectionCaption\": \"What to scrape\",\n      \"sectionDescription\": \"Pick one mode and fill the matching target fields. Empty fields from other modes are ignored.\"\n    },\n    \"keywords\": {\n      \"title\": \"Place keywords\",\n      \"type\": \"array\",\n      \"description\": \"Place names, landmarks, venues or addresses to search on Snap Map. Used in Search places mode. Examples: Times Square, Eiffel Tower, Tokyo Station.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"prefill\": [\n        \"Times Square\"\n      ]\n    },\n    \"placeUrls\": {\n      \"title\": \"Place URLs or IDs\",\n      \"type\": \"array\",\n      \"description\": \"Snapchat place page URLs, /place/ paths, or bare place UUIDs. Used in Get details mode. Example: https://www.snapchat.com/place/times-square/c8b4f0ee-9992-11e8-88c9-673ed985ff70.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"cityUrls\": {\n      \"title\": \"Cities\",\n      \"type\": \"array\",\n      \"description\": \"US city names, Snapchat local URLs, or local paths for Browse mode. Examples: new-york, chicago, https://www.snapchat.com/local/united-states/california/los-angeles.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"categories\": {\n      \"title\": \"Categories\",\n      \"type\": \"array\",\n      \"description\": \"Optional category slugs for Browse mode, such as bars, restaurants, coffee-shops, historic-landmarks or parks. Leave empty to use the city hub's six featured categories.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"prefill\": []\n    },\n    \"resultTypes\": {\n      \"title\": \"Result types\",\n      \"type\": \"array\",\n      \"description\": \"Which Explore result groups to return in Search places mode. Places is the Snap Map place search; the other groups are the public entities Snapchat shows for the same keyword.\",\n      \"editor\": \"select\",\n      \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"places\",\n          \"spotlight\",\n          \"users\",\n          \"profiles\",\n          \"publishers\",\n          \"episodes\",\n          \"lenses\"\n        ],\n        \"enumTitles\": [\n          \"Places\",\n          \"Spotlight videos\",\n          \"Users\",\n          \"Public profiles\",\n          \"Publishers\",\n          \"Episodes\",\n          \"Lenses\"\n        ]\n      },\n      \"default\": [\n        \"places\"\n      ],\n      \"prefill\": [\n        \"places\"\n      ]\n    },\n    \"outputType\": {\n      \"title\": \"Output rows\",\n      \"type\": \"string\",\n      \"description\": \"Place records keep one row per place with live snaps nested. Live snap records flatten every live snap into its own row with the place's coordinates, which is easier for maps and time-series analysis.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"placeRecords\",\n        \"liveSnapRecords\"\n      ],\n      \"enumTitles\": [\n        \"One row per place\",\n        \"One row per live snap\"\n      ],\n      \"default\": \"placeRecords\",\n      \"prefill\": \"placeRecords\"\n    },\n    \"maxResultsPerKeyword\": {\n      \"title\": \"Max results per keyword\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum rows to keep for each result type per keyword. Snapchat returns up to 10 places and roughly 20-24 items for the other groups.\",\n      \"default\": 10,\n      \"minimum\": 1,\n      \"maximum\": 50,\n      \"prefill\": 1\n    },\n    \"maxPlaces\": {\n      \"title\": \"Max places\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum places to process in Get details mode.\",\n      \"default\": 100,\n      \"minimum\": 1,\n      \"maximum\": 500,\n      \"prefill\": 1\n    },\n    \"maxPlacesPerCity\": {\n      \"title\": \"Max places per city\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum places to keep per city in Browse mode after merging the hub categories.\",\n      \"default\": 100,\n      \"minimum\": 1,\n      \"maximum\": 500,\n      \"prefill\": 20\n    },\n    \"maxSnapsPerPlace\": {\n      \"title\": \"Max live snaps per place\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum live snaps to keep per place. Snapchat's public page exposes a sample of 2-36 current snaps per place.\",\n      \"default\": 10,\n      \"minimum\": 1,\n      \"maximum\": 50,\n      \"prefill\": 3\n    },\n    \"includeSnapData\": {\n      \"title\": \"Include live snaps\",\n      \"type\": \"boolean\",\n      \"description\": \"Add the public snap sample for each place with media URL, thumbnail, creator and timestamp. Snapchat mixes recent map posts with older Spotlight shares, so use the age filter below to keep only fresh posts. Also fills the legacy first-snap fields.\",\n      \"default\": true,\n      \"prefill\": true\n    },\n    \"includePlaceDetails\": {\n      \"title\": \"Include full place details\",\n      \"type\": \"boolean\",\n      \"description\": \"Open each place page to fill coordinates, address, phone, website, category, rating, reviews, opening hours, popularity and nearby places. Turn off for a faster search-card-only run. Nearby places, reviews, favorite sorting, live-snap output and the live-snap filter open place pages automatically because those values only exist there.\",\n      \"default\": true,\n      \"prefill\": true\n    },\n    \"includeNearbyPlaces\": {\n      \"title\": \"Include nearby places\",\n      \"type\": \"boolean\",\n      \"description\": \"Add the places Snapchat lists at the same location, with their coordinates and categories.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"includeReviews\": {\n      \"title\": \"Include place reviews\",\n      \"type\": \"boolean\",\n      \"description\": \"Add up to 20 public place reviews with rating, text, date and source URL.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"includePopularityHours\": {\n      \"title\": \"Include 7x24 popularity\",\n      \"type\": \"boolean\",\n      \"description\": \"Add Snapchat's 168 hourly popularity values per place (7 days x 24 hours) plus the peak hour and day index. This is the per-place heatmap signal.\",\n      \"default\": true,\n      \"prefill\": true\n    },\n    \"minRating\": {\n      \"title\": \"Minimum rating\",\n      \"type\": \"number\",\n      \"description\": \"Keep only places whose public rating is at least this value. Places without a rating are dropped when this is above 0.\",\n      \"default\": 0,\n      \"minimum\": 0,\n      \"maximum\": 5,\n      \"prefill\": 0,\n      \"sectionCaption\": \"Filters and sorting\",\n      \"sectionDescription\": \"Applied after the selected enrichment so every filter sees real values.\"\n    },\n    \"requireLiveSnaps\": {\n      \"title\": \"Only places with live snaps\",\n      \"type\": \"boolean\",\n      \"description\": \"Drop places that currently have no public live snaps.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"snapMaxAgeHours\": {\n      \"title\": \"Only snaps newer than (hours)\",\n      \"type\": \"integer\",\n      \"description\": \"Keep only snaps posted within this many hours. Set 0 to keep every snap the public page returns. liveSnapCount and latestSnapAt describe only the kept snaps, and the live-snap filter uses that kept count.\",\n      \"default\": 0,\n      \"minimum\": 0,\n      \"maximum\": 168,\n      \"prefill\": 0\n    },\n    \"sortBy\": {\n      \"title\": \"Sort by\",\n      \"type\": \"string\",\n      \"description\": \"Order places by Snapchat's source order, rating, favorite count or number of live snaps.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"source\",\n        \"rating\",\n        \"favorites\",\n        \"liveSnaps\"\n      ],\n      \"enumTitles\": [\n        \"Snapchat source order\",\n        \"Rating (high to low)\",\n        \"Favorites (high to low)\",\n        \"Live snaps (high to low)\"\n      ],\n      \"default\": \"source\",\n      \"prefill\": \"source\"\n    },\n    \"proxyConfiguration\": {\n      \"title\": \"Proxy configuration\",\n      \"type\": \"object\",\n      \"description\": \"Optional. The public Snapchat pages used here work without a proxy.\",\n      \"editor\": \"proxy\",\n      \"nullable\": true,\n      \"sectionCaption\": \"Advanced\",\n      \"sectionDescription\": \"Optional infrastructure settings. No proxy or credentials are needed for normal runs.\"\n    }\n  },\n  \"required\": []\n}",
    "readme": "# Snapchat Snap Map Place & Live Snap Extractor\n\nSnap Map shows the public snaps and places people are posting about right now. This actor reads Snapchat's public web pages and turns them into a clean dataset: place coordinates, address, category, rating, opening hours, a 7×24 popularity heatmap and the public snap sample at each place, with media URLs, creators and timestamps. Search by keyword, paste place links, or browse US cities and categories. No Snapchat account, cookies, API key or proxy setup is needed.\n\n## What you can collect\n\n- **Place search** — one keyword returns the Snap Map places Snapchat matches, plus the public Spotlight videos, creators, profiles, publishers, episodes and lenses shown for the same query.\n- **Place details** — paste place URLs or UUIDs and get the full public place profile: geometry, address, phone, website, category, rating and reviews, opening hours, favorites and nearby places.\n- **Live snaps** — every place page carries a sample of public snaps posted at or shared about the place: media URL, thumbnail, video or image type, creator username and display name, timestamp and snap source (`map` or `spotlight`). Snapchat mixes recent map posts with older Spotlight shares, so use `snapMaxAgeHours` when you need a fresh-only feed.\n- **7×24 popularity** — Snapchat's hourly popularity values for the whole week (168 values), plus the peak hour and day index. Use it as a per-place heatmap signal.\n- **US city and category discovery** — browse a city hub or a category page such as bars, restaurants or historic landmarks. Each row includes the live-snap count, rating, popularity hours and coordinates, which makes it easy to map activity.\n- **Flat live-snap rows** — switch the output to one row per snap when you want a snap-level dataset instead of nested arrays.\n\n## Modes\n\n| Mode | What it does | Main input |\n|---|---|---|\n| `searchPlaces` | Search Snap Map and optionally the other Explore result groups | `keywords` |\n| `placeDetails` | Load full details for specific places | `placeUrls` |\n| `browseLocal` | Browse a US city hub or category pages | `cityUrls`, optional `categories` |\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | select | `searchPlaces` | Which collection mode to run |\n| `keywords` | string list | — | Place names or landmarks for search mode; the form prefill uses `[\"Times Square\"]` |\n| `placeUrls` | string list | — | Full place URLs, `/place/...` paths or bare place UUIDs |\n| `cityUrls` | string list | — | US city names, Snapchat local URLs or local paths |\n| `categories` | string list | — | Category slugs for browse mode, e.g. `bars`, `restaurants`, `historic-landmarks` |\n| `resultTypes` | multi-select | `[\"places\"]` | Explore groups to return: places, spotlight, users, profiles, publishers, episodes, lenses |\n| `outputType` | select | `placeRecords` | One row per place, or one row per live snap |\n| `maxResultsPerKeyword` | integer | 10 | Cap per result type per keyword |\n| `maxPlaces` | integer | 100 | Cap for place-details mode |\n| `maxPlacesPerCity` | integer | 100 | Cap per city in browse mode |\n| `maxSnapsPerPlace` | integer | 10 | Live snaps to keep per place |\n| `includeSnapData` | boolean | true | Add the public snap sample and the legacy first-snap fields |\n| `includePlaceDetails` | boolean | true | Open each place page for coordinates, contact, rating and hours; nearby/reviews/live-snap output open pages automatically |\n| `includeNearbyPlaces` | boolean | false | Add the places Snapchat lists at the same location |\n| `includeReviews` | boolean | false | Add up to 20 public place reviews |\n| `includePopularityHours` | boolean | true | Add the 168-value popularity series and peak |\n| `minRating` | number | 0 | Keep places at or above this rating |\n| `requireLiveSnaps` | boolean | false | Keep only places that currently have public snaps |\n| `snapMaxAgeHours` | integer | 0 | Keep only snaps newer than this; 0 keeps all. Counts and `latestSnapAt` reflect kept snaps |\n| `sortBy` | select | `source` | Order by source, rating, favorites or live-snap count |\n| `proxyConfiguration` | proxy | — | Optional; the public pages work without a proxy |\n\nLegacy tasks keep working: `maxPlacesPerKeyword` from older versions is read in code and mapped onto `maxResultsPerKeyword`.\n\n## Output\n\nEvery row has `recordType` so mixed datasets stay readable: `place`, `liveSnap`, `spotlight`, `user`, `profile`, `publisher`, `episode` or `lens`. Empty fields are omitted, never written as `null`, `\"\"` or `[]`.\n\n### Place fields\n\n| Field | Description |\n|---|---|\n| `placeId` | Snapchat place UUID |\n| `displayName`, `placeUrl` | Place name and canonical Snapchat URL |\n| `lat`, `lng`, `boundingBox` | Centroid and southwest/northeast bounds |\n| `address` | Street, city, region, postal code, country and formatted address |\n| `categoryName`, `categoryId`, `placeType` | Snapchat category and place type |\n| `phone`, `email`, `website`, `menuUrl`, `reservationUrl`, `storeUrl` | Public contact and action links |\n| `rating`, `reviewCount`, `ratingProvider`, `ratings` | Public rating summary (provider value is rounded to 2 decimals) |\n| `reviews` | Optional review rows with text, rating, date and source URL |\n| `openingHours` | Day-by-day ranges, special hours and time zone |\n| `isOpen` | Open-now flag from local discovery pages |\n| `favoriteCount`, `favoriteDisplayCount` | Snapchat favorite count |\n| `profilePhotoUrl`, `profilePhotoProvider`, `photoUrls` | Public photos |\n| `popularityHours` | 168 hourly values, 7 days × 24 hours |\n| `popularityPeakHour`, `popularityPeakDayIndex`, `popularityPeakValue` | Peak of the series (day index 0 = Sunday) |\n| `liveSnapCount`, `latestSnapAt`, `liveSnaps` | Public snap sample after `snapMaxAgeHours` filtering, its latest timestamp and up to `maxSnapsPerPlace` rows |\n| `nearbyPlaces` | Optional places at the same location |\n| `placeHierarchy` | Neighborhood, ZIP, city and state breadcrumbs |\n| `snapCount`, `firstSnapId`, `thumbnailUrl` | Legacy place-level snap fields |\n| `snapId`, `mediaUrl`, `previewUrl`, `mediaType`, `postedAt`, `creatorUsername`, `creatorDisplayName` | Legacy first-snap aliases |\n| `scrapedAt`, `sourcePage` | Collection timestamp and source surface |\n\n### Live snap row fields (`outputType: liveSnapRecords`)\n\n`snapId`, `placeId`, `placeName`, `categoryName`, `city`, `lat`, `lng`, `mediaUrl`, `thumbnailUrl`, `previewUrl`, `mediaType`, `storyType`, `duration`, `postedAt`, `creatorUsername`, `creatorDisplayName`, `creatorUserId`, `scrapedAt`.\n\n### Example: search\n\n```json\n{\n  \"mode\": \"searchPlaces\",\n  \"keywords\": [\"Times Square\"],\n  \"maxResultsPerKeyword\": 3,\n  \"includePlaceDetails\": true,\n  \"includeSnapData\": true,\n  \"includePopularityHours\": true\n}\n```\n\n### Example: place details\n\n```json\n{\n  \"mode\": \"placeDetails\",\n  \"placeUrls\": [\"https://www.snapchat.com/place/times-square/c8b4f0ee-9992-11e8-88c9-673ed985ff70\"],\n  \"includeNearbyPlaces\": true,\n  \"includeReviews\": true\n}\n```\n\n### Example: city browse\n\n```json\n{\n  \"mode\": \"browseLocal\",\n  \"cityUrls\": [\"new-york\"],\n  \"categories\": [\"bars\", \"restaurants\"],\n  \"outputType\": \"liveSnapRecords\",\n  \"maxSnapsPerPlace\": 5\n}\n```\n\n## How the popularity heatmap works\n\nSnapchat publishes 168 popularity integers per place, one for every hour of the week. The array starts at hour 0 and runs through the week, so `popularityPeakHour` is `index % 24` and `popularityPeakDayIndex` is `index // 24` (0 = Sunday). The values are relative popularity, not absolute visitor counts.\n\n## Limits\n\n- **Snap Map mobile API is not used.** The app's private endpoints (`ms.sc-jpl.com`) refuse every web and cloud TLS client, so this actor uses Snapchat's public web pages instead. Live snaps and popularity come from the public place pages.\n- **Local discovery covers the United States.** Snapchat's `/local` directory returns 404 outside the US.\n- **20 places per city or category page.** The page reports a larger total but serves a 20-row display cap; split by category to get more rows.\n- **Search groups are capped by Snapchat.** Places return up to 10 rows and other groups about 20–24; there is no cursor.\n- **Live snaps are a public sample, not a real-time feed.** A place page exposes roughly 2–36 snaps mixing recent map posts with older Spotlight shares (verified samples span hours to over a year). `snapMaxAgeHours` keeps only the age you want, and `liveSnapCount` reflects the kept rows. City pages carry their own older story samples; the default `includePlaceDetails: true` and the `liveSnapRecords` output read the place pages instead.\n- **Some legacy snap fields are gone.** The 2026 page payload no longer publishes duration, width, height, overlay text or sponsored flags, so those keys appear only when Snapchat supplies them.\n\n## FAQ\n\n**Do I need a Snapchat account or cookies?**\nNo. Every surface used here is public.\n\n**Do I need a proxy?**\nNo. The pages load directly. A proxy field is available if you want extra redundancy.\n\n**Why is a field missing on some places?**\nSnapchat does not publish every field for every place. Missing values are omitted rather than filled with placeholders.\n\n**Can I get snaps for a radius or a map tile?**\nThat is the Snap Map app API, which is not reachable from web clients. Use place details or city browse for public snap data, and join `lat`/`lng` with your own geometry.\n\n**Are media URLs permanent?**\nThey are public CDN links that work without cookies or a Referer and are cached for a day. Snapchat can expire them, so download the media promptly if you need the file.\n\n**Is this affiliated with Snapchat?**\nNo. This actor independently reads Snapchat's public web pages and is not affiliated with or endorsed by Snap Inc.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "snapchat-snap-map-place-and-live-snap-extractor",
      "title": "Snapchat Snap Map Place & Live Snap Extractor",
      "description": "Search Snap Map places, collect current public live snaps and 7x24 popularity, and browse US city and category place rankings by keyword, place URL or city. No Snapchat login, cookies or proxy setup.",
      "version": "1.0",
      "buildTag": "latest",
      "meta": {
        "templateId": "python"
      },
      "input": {
        "title": "Snapchat Snap Map Scraper",
        "description": "Collect Snap Map places, live public snaps and 7x24 popularity data from Snapchat's public web pages. Search by place keyword, look up specific places, or browse US cities and categories. No Snapchat account, cookies or proxy setup required.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "mode": {
            "title": "Mode",
            "type": "string",
            "description": "Choose what to scrape: search Snap Map places by keyword, look up specific place URLs or IDs, or browse US cities and categories.",
            "editor": "select",
            "enum": [
              "searchPlaces",
              "placeDetails",
              "browseLocal"
            ],
            "enumTitles": [
              "Search places by keyword",
              "Get details for specific places",
              "Browse US cities and categories"
            ],
            "default": "searchPlaces",
            "prefill": "searchPlaces",
            "sectionCaption": "What to scrape",
            "sectionDescription": "Pick one mode and fill the matching target fields. Empty fields from other modes are ignored."
          },
          "keywords": {
            "title": "Place keywords",
            "type": "array",
            "description": "Place names, landmarks, venues or addresses to search on Snap Map. Used in Search places mode. Examples: Times Square, Eiffel Tower, Tokyo Station.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "prefill": [
              "Times Square"
            ]
          },
          "placeUrls": {
            "title": "Place URLs or IDs",
            "type": "array",
            "description": "Snapchat place page URLs, /place/ paths, or bare place UUIDs. Used in Get details mode. Example: https://www.snapchat.com/place/times-square/c8b4f0ee-9992-11e8-88c9-673ed985ff70.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "prefill": []
          },
          "cityUrls": {
            "title": "Cities",
            "type": "array",
            "description": "US city names, Snapchat local URLs, or local paths for Browse mode. Examples: new-york, chicago, https://www.snapchat.com/local/united-states/california/los-angeles.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "prefill": []
          },
          "categories": {
            "title": "Categories",
            "type": "array",
            "description": "Optional category slugs for Browse mode, such as bars, restaurants, coffee-shops, historic-landmarks or parks. Leave empty to use the city hub's six featured categories.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "prefill": []
          },
          "resultTypes": {
            "title": "Result types",
            "type": "array",
            "description": "Which Explore result groups to return in Search places mode. Places is the Snap Map place search; the other groups are the public entities Snapchat shows for the same keyword.",
            "editor": "select",
            "items": {
              "type": "string",
              "enum": [
                "places",
                "spotlight",
                "users",
                "profiles",
                "publishers",
                "episodes",
                "lenses"
              ],
              "enumTitles": [
                "Places",
                "Spotlight videos",
                "Users",
                "Public profiles",
                "Publishers",
                "Episodes",
                "Lenses"
              ]
            },
            "default": [
              "places"
            ],
            "prefill": [
              "places"
            ]
          },
          "outputType": {
            "title": "Output rows",
            "type": "string",
            "description": "Place records keep one row per place with live snaps nested. Live snap records flatten every live snap into its own row with the place's coordinates, which is easier for maps and time-series analysis.",
            "editor": "select",
            "enum": [
              "placeRecords",
              "liveSnapRecords"
            ],
            "enumTitles": [
              "One row per place",
              "One row per live snap"
            ],
            "default": "placeRecords",
            "prefill": "placeRecords"
          },
          "maxResultsPerKeyword": {
            "title": "Max results per keyword",
            "type": "integer",
            "description": "Maximum rows to keep for each result type per keyword. Snapchat returns up to 10 places and roughly 20-24 items for the other groups.",
            "default": 10,
            "minimum": 1,
            "maximum": 50,
            "prefill": 1
          },
          "maxPlaces": {
            "title": "Max places",
            "type": "integer",
            "description": "Maximum places to process in Get details mode.",
            "default": 100,
            "minimum": 1,
            "maximum": 500,
            "prefill": 1
          },
          "maxPlacesPerCity": {
            "title": "Max places per city",
            "type": "integer",
            "description": "Maximum places to keep per city in Browse mode after merging the hub categories.",
            "default": 100,
            "minimum": 1,
            "maximum": 500,
            "prefill": 20
          },
          "maxSnapsPerPlace": {
            "title": "Max live snaps per place",
            "type": "integer",
            "description": "Maximum live snaps to keep per place. Snapchat's public page exposes a sample of 2-36 current snaps per place.",
            "default": 10,
            "minimum": 1,
            "maximum": 50,
            "prefill": 3
          },
          "includeSnapData": {
            "title": "Include live snaps",
            "type": "boolean",
            "description": "Add the public snap sample for each place with media URL, thumbnail, creator and timestamp. Snapchat mixes recent map posts with older Spotlight shares, so use the age filter below to keep only fresh posts. Also fills the legacy first-snap fields.",
            "default": true,
            "prefill": true
          },
          "includePlaceDetails": {
            "title": "Include full place details",
            "type": "boolean",
            "description": "Open each place page to fill coordinates, address, phone, website, category, rating, reviews, opening hours, popularity and nearby places. Turn off for a faster search-card-only run. Nearby places, reviews, favorite sorting, live-snap output and the live-snap filter open place pages automatically because those values only exist there.",
            "default": true,
            "prefill": true
          },
          "includeNearbyPlaces": {
            "title": "Include nearby places",
            "type": "boolean",
            "description": "Add the places Snapchat lists at the same location, with their coordinates and categories.",
            "default": false,
            "prefill": false
          },
          "includeReviews": {
            "title": "Include place reviews",
            "type": "boolean",
            "description": "Add up to 20 public place reviews with rating, text, date and source URL.",
            "default": false,
            "prefill": false
          },
          "includePopularityHours": {
            "title": "Include 7x24 popularity",
            "type": "boolean",
            "description": "Add Snapchat's 168 hourly popularity values per place (7 days x 24 hours) plus the peak hour and day index. This is the per-place heatmap signal.",
            "default": true,
            "prefill": true
          },
          "minRating": {
            "title": "Minimum rating",
            "type": "number",
            "description": "Keep only places whose public rating is at least this value. Places without a rating are dropped when this is above 0.",
            "default": 0,
            "minimum": 0,
            "maximum": 5,
            "prefill": 0,
            "sectionCaption": "Filters and sorting",
            "sectionDescription": "Applied after the selected enrichment so every filter sees real values."
          },
          "requireLiveSnaps": {
            "title": "Only places with live snaps",
            "type": "boolean",
            "description": "Drop places that currently have no public live snaps.",
            "default": false,
            "prefill": false
          },
          "snapMaxAgeHours": {
            "title": "Only snaps newer than (hours)",
            "type": "integer",
            "description": "Keep only snaps posted within this many hours. Set 0 to keep every snap the public page returns. liveSnapCount and latestSnapAt describe only the kept snaps, and the live-snap filter uses that kept count.",
            "default": 0,
            "minimum": 0,
            "maximum": 168,
            "prefill": 0
          },
          "sortBy": {
            "title": "Sort by",
            "type": "string",
            "description": "Order places by Snapchat's source order, rating, favorite count or number of live snaps.",
            "editor": "select",
            "enum": [
              "source",
              "rating",
              "favorites",
              "liveSnaps"
            ],
            "enumTitles": [
              "Snapchat source order",
              "Rating (high to low)",
              "Favorites (high to low)",
              "Live snaps (high to low)"
            ],
            "default": "source",
            "prefill": "source"
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Optional. The public Snapchat pages used here work without a proxy.",
            "editor": "proxy",
            "nullable": true,
            "sectionCaption": "Advanced",
            "sectionDescription": "Optional infrastructure settings. No proxy or credentials are needed for normal runs."
          }
        },
        "required": []
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Snapchat Snap Map Place & Live Snap Extractor Output",
        "description": "Snap Map place and live snap rows with coordinates, categories, ratings, popularity, media URLs, timestamps and creator details.",
        "properties": {
          "records": {
            "type": "string",
            "title": "Snap Map records",
            "description": "Dataset containing all scraped Snap Map places, live snaps and related Explore entities.",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "dockerfile": "../Dockerfile",
      "readme": "# Snapchat Snap Map Place & Live Snap Extractor\n\nSnap Map shows the public snaps and places people are posting about right now. This actor reads Snapchat's public web pages and turns them into a clean dataset: place coordinates, address, category, rating, opening hours, a 7×24 popularity heatmap and the public snap sample at each place, with media URLs, creators and timestamps. Search by keyword, paste place links, or browse US cities and categories. No Snapchat account, cookies, API key or proxy setup is needed.\n\n## What you can collect\n\n- **Place search** — one keyword returns the Snap Map places Snapchat matches, plus the public Spotlight videos, creators, profiles, publishers, episodes and lenses shown for the same query.\n- **Place details** — paste place URLs or UUIDs and get the full public place profile: geometry, address, phone, website, category, rating and reviews, opening hours, favorites and nearby places.\n- **Live snaps** — every place page carries a sample of public snaps posted at or shared about the place: media URL, thumbnail, video or image type, creator username and display name, timestamp and snap source (`map` or `spotlight`). Snapchat mixes recent map posts with older Spotlight shares, so use `snapMaxAgeHours` when you need a fresh-only feed.\n- **7×24 popularity** — Snapchat's hourly popularity values for the whole week (168 values), plus the peak hour and day index. Use it as a per-place heatmap signal.\n- **US city and category discovery** — browse a city hub or a category page such as bars, restaurants or historic landmarks. Each row includes the live-snap count, rating, popularity hours and coordinates, which makes it easy to map activity.\n- **Flat live-snap rows** — switch the output to one row per snap when you want a snap-level dataset instead of nested arrays.\n\n## Modes\n\n| Mode | What it does | Main input |\n|---|---|---|\n| `searchPlaces` | Search Snap Map and optionally the other Explore result groups | `keywords` |\n| `placeDetails` | Load full details for specific places | `placeUrls` |\n| `browseLocal` | Browse a US city hub or category pages | `cityUrls`, optional `categories` |\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `mode` | select | `searchPlaces` | Which collection mode to run |\n| `keywords` | string list | — | Place names or landmarks for search mode; the form prefill uses `[\"Times Square\"]` |\n| `placeUrls` | string list | — | Full place URLs, `/place/...` paths or bare place UUIDs |\n| `cityUrls` | string list | — | US city names, Snapchat local URLs or local paths |\n| `categories` | string list | — | Category slugs for browse mode, e.g. `bars`, `restaurants`, `historic-landmarks` |\n| `resultTypes` | multi-select | `[\"places\"]` | Explore groups to return: places, spotlight, users, profiles, publishers, episodes, lenses |\n| `outputType` | select | `placeRecords` | One row per place, or one row per live snap |\n| `maxResultsPerKeyword` | integer | 10 | Cap per result type per keyword |\n| `maxPlaces` | integer | 100 | Cap for place-details mode |\n| `maxPlacesPerCity` | integer | 100 | Cap per city in browse mode |\n| `maxSnapsPerPlace` | integer | 10 | Live snaps to keep per place |\n| `includeSnapData` | boolean | true | Add the public snap sample and the legacy first-snap fields |\n| `includePlaceDetails` | boolean | true | Open each place page for coordinates, contact, rating and hours; nearby/reviews/live-snap output open pages automatically |\n| `includeNearbyPlaces` | boolean | false | Add the places Snapchat lists at the same location |\n| `includeReviews` | boolean | false | Add up to 20 public place reviews |\n| `includePopularityHours` | boolean | true | Add the 168-value popularity series and peak |\n| `minRating` | number | 0 | Keep places at or above this rating |\n| `requireLiveSnaps` | boolean | false | Keep only places that currently have public snaps |\n| `snapMaxAgeHours` | integer | 0 | Keep only snaps newer than this; 0 keeps all. Counts and `latestSnapAt` reflect kept snaps |\n| `sortBy` | select | `source` | Order by source, rating, favorites or live-snap count |\n| `proxyConfiguration` | proxy | — | Optional; the public pages work without a proxy |\n\nLegacy tasks keep working: `maxPlacesPerKeyword` from older versions is read in code and mapped onto `maxResultsPerKeyword`.\n\n## Output\n\nEvery row has `recordType` so mixed datasets stay readable: `place`, `liveSnap`, `spotlight`, `user`, `profile`, `publisher`, `episode` or `lens`. Empty fields are omitted, never written as `null`, `\"\"` or `[]`.\n\n### Place fields\n\n| Field | Description |\n|---|---|\n| `placeId` | Snapchat place UUID |\n| `displayName`, `placeUrl` | Place name and canonical Snapchat URL |\n| `lat`, `lng`, `boundingBox` | Centroid and southwest/northeast bounds |\n| `address` | Street, city, region, postal code, country and formatted address |\n| `categoryName`, `categoryId`, `placeType` | Snapchat category and place type |\n| `phone`, `email`, `website`, `menuUrl`, `reservationUrl`, `storeUrl` | Public contact and action links |\n| `rating`, `reviewCount`, `ratingProvider`, `ratings` | Public rating summary (provider value is rounded to 2 decimals) |\n| `reviews` | Optional review rows with text, rating, date and source URL |\n| `openingHours` | Day-by-day ranges, special hours and time zone |\n| `isOpen` | Open-now flag from local discovery pages |\n| `favoriteCount`, `favoriteDisplayCount` | Snapchat favorite count |\n| `profilePhotoUrl`, `profilePhotoProvider`, `photoUrls` | Public photos |\n| `popularityHours` | 168 hourly values, 7 days × 24 hours |\n| `popularityPeakHour`, `popularityPeakDayIndex`, `popularityPeakValue` | Peak of the series (day index 0 = Sunday) |\n| `liveSnapCount`, `latestSnapAt`, `liveSnaps` | Public snap sample after `snapMaxAgeHours` filtering, its latest timestamp and up to `maxSnapsPerPlace` rows |\n| `nearbyPlaces` | Optional places at the same location |\n| `placeHierarchy` | Neighborhood, ZIP, city and state breadcrumbs |\n| `snapCount`, `firstSnapId`, `thumbnailUrl` | Legacy place-level snap fields |\n| `snapId`, `mediaUrl`, `previewUrl`, `mediaType`, `postedAt`, `creatorUsername`, `creatorDisplayName` | Legacy first-snap aliases |\n| `scrapedAt`, `sourcePage` | Collection timestamp and source surface |\n\n### Live snap row fields (`outputType: liveSnapRecords`)\n\n`snapId`, `placeId`, `placeName`, `categoryName`, `city`, `lat`, `lng`, `mediaUrl`, `thumbnailUrl`, `previewUrl`, `mediaType`, `storyType`, `duration`, `postedAt`, `creatorUsername`, `creatorDisplayName`, `creatorUserId`, `scrapedAt`.\n\n### Example: search\n\n```json\n{\n  \"mode\": \"searchPlaces\",\n  \"keywords\": [\"Times Square\"],\n  \"maxResultsPerKeyword\": 3,\n  \"includePlaceDetails\": true,\n  \"includeSnapData\": true,\n  \"includePopularityHours\": true\n}\n```\n\n### Example: place details\n\n```json\n{\n  \"mode\": \"placeDetails\",\n  \"placeUrls\": [\"https://www.snapchat.com/place/times-square/c8b4f0ee-9992-11e8-88c9-673ed985ff70\"],\n  \"includeNearbyPlaces\": true,\n  \"includeReviews\": true\n}\n```\n\n### Example: city browse\n\n```json\n{\n  \"mode\": \"browseLocal\",\n  \"cityUrls\": [\"new-york\"],\n  \"categories\": [\"bars\", \"restaurants\"],\n  \"outputType\": \"liveSnapRecords\",\n  \"maxSnapsPerPlace\": 5\n}\n```\n\n## How the popularity heatmap works\n\nSnapchat publishes 168 popularity integers per place, one for every hour of the week. The array starts at hour 0 and runs through the week, so `popularityPeakHour` is `index % 24` and `popularityPeakDayIndex` is `index // 24` (0 = Sunday). The values are relative popularity, not absolute visitor counts.\n\n## Limits\n\n- **Snap Map mobile API is not used.** The app's private endpoints (`ms.sc-jpl.com`) refuse every web and cloud TLS client, so this actor uses Snapchat's public web pages instead. Live snaps and popularity come from the public place pages.\n- **Local discovery covers the United States.** Snapchat's `/local` directory returns 404 outside the US.\n- **20 places per city or category page.** The page reports a larger total but serves a 20-row display cap; split by category to get more rows.\n- **Search groups are capped by Snapchat.** Places return up to 10 rows and other groups about 20–24; there is no cursor.\n- **Live snaps are a public sample, not a real-time feed.** A place page exposes roughly 2–36 snaps mixing recent map posts with older Spotlight shares (verified samples span hours to over a year). `snapMaxAgeHours` keeps only the age you want, and `liveSnapCount` reflects the kept rows. City pages carry their own older story samples; the default `includePlaceDetails: true` and the `liveSnapRecords` output read the place pages instead.\n- **Some legacy snap fields are gone.** The 2026 page payload no longer publishes duration, width, height, overlay text or sponsored flags, so those keys appear only when Snapchat supplies them.\n\n## FAQ\n\n**Do I need a Snapchat account or cookies?**\nNo. Every surface used here is public.\n\n**Do I need a proxy?**\nNo. The pages load directly. A proxy field is available if you want extra redundancy.\n\n**Why is a field missing on some places?**\nSnapchat does not publish every field for every place. Missing values are omitted rather than filled with placeholders.\n\n**Can I get snaps for a radius or a map tile?**\nThat is the Snap Map app API, which is not reachable from web clients. Use place details or city browse for public snap data, and join `lat`/`lng` with your own geometry.\n\n**Are media URLs permanent?**\nThey are public CDN links that work without cookies or a Referer and are cached for a day. Snapchat can expire them, so download the media promptly if you need the file.\n\n**Is this affiliated with Snapchat?**\nNo. This actor independently reads Snapchat's public web pages and is not affiliated with or endorsed by Snap Inc.\n"
    },
    "buildNumber": "1.0.2",
    "imageDigest": "328c1332319309714dc11334a006533d38a63efc046b683f1ffeec5546246251",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "1.0"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.004074444444444445
    }
  }
}