Instagram Posts Scraper With Tagged Places & Coordinates
Pricing
from $2.99 / 1,000 results
Instagram Posts Scraper With Tagged Places & Coordinates
Instagram Posts Scraper — Scrape Instagram posts with captions, media details, likes, timestamps, tagged places, location names, and geographic coordinates. Extract structured location and engagement data for content research, local trend analysis, competitor monitoring, and social insights.
Pricing
from $2.99 / 1,000 results
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
0
Bookmarked
12
Total users
2
Monthly active users
3 days ago
Last modified
Categories
Share
Instagram Posts Scraper — Tagged Places, Coordinates & Engagement
Instagram Posts Scraper With Tagged Places & Coordinates pulls posts from any public Instagram profile, username, or post shortcode and returns them as structured JSON — post_url, taken_at, like_count, comment_count, plus a taggedPlace object with placeName, GPS lat/lng, address, and city for every geotagged post. Travel marketers, local-content researchers, and geospatial analysts use it to map where an account posts from, not just what it posts. Turn on the only-geotagged filter and each run also adds a per-profile roll-up of that creator's most-tagged places.
What is Instagram Posts Scraper With Tagged Places & Coordinates?
It is an Apify Actor that scrapes posts from a list of Instagram profile URLs, usernames, or post shortcodes and returns one structured JSON row per post, plus an optional per-profile summary row. No Instagram account, login, or session cookie is required — the Actor reads each profile's public page to extract the tokens it needs, then calls Instagram's own post-feed endpoint.
- 🔗 Flexible targeting — accepts full profile URLs, plain usernames, or post shortcodes in the same list; the type is auto-detected, and shortcodes are resolved to their author's username automatically.
- 📍 Structured tagged-place fields —
placeName,lat/lng,address,city, andexternalIdparsed out of Instagram's rawlocationobject into a cleantaggedPlacefield, plus ahasLocationflag on every post. - 🔎 Only-geotagged mode —
onlyGeotaggedskips posts with no tagged place and keeps scanning further pages until it collectspostsPerProfilegeotagged posts (or the profile/date range runs out). - 🏆 Per-profile top-places roll-up —
topPlacesPerProfileadds onelocationSummaryrow per profile, ranking that creator's most-frequently-tagged places by scanned-post count. - 📅 Absolute or relative date filtering —
dateFilterType+filterDatekeep only posts newer than a calendar date or a relative window like30d. - 🌐 Proxy-backed requests — every request runs through
proxyConfigurationviaActor.create_proxy_configuration, defaulting to Apify'sRESIDENTIALgroup when left unset.
Results land in the Actor's default dataset and can be downloaded as JSON, CSV, or Excel, or read back with the Apify API — standard Apify dataset export, not a feature specific to this Actor.
What data can I extract with Instagram Posts Scraper?
Every scraped post is returned with the fields below, plus every other field Instagram's own post-feed API includes for that post (media URLs, dimensions, caption object, owner data, and more) — the Actor passes those through verbatim rather than stripping or renaming them.
| Field | Example Value | Use Case |
|---|---|---|
type | "post" or "locationSummary" | Tells you whether the row is a post or the per-profile roll-up |
code / short_code | "DO8fSwLiNU-" | Instagram's shortcode for the post |
post_url | "https://www.instagram.com/p/DO8fSwLiNU-/" | Direct permalink to the post |
scraped_username | "natgeo" | Which profile this row came from |
taken_at | 1758631325 | Unix timestamp the post was published |
scraped_at | 1758631400 | Unix timestamp this run collected the row |
hasLocation | true | Whether the post's creator tagged a place |
taggedPlace.placeId | "212988663" | Instagram's internal place ID |
taggedPlace.placeName | "Yellowstone National Park" | The tagged place's name |
taggedPlace.lat / taggedPlace.lng | 44.4279 / -110.5885 | GPS coordinates of the tagged place |
taggedPlace.address | null | Street address, when Instagram has one on file |
taggedPlace.city | "Yellowstone National Park" | City name for the tagged place |
taggedPlace.externalId | null | External place-directory ID (e.g. Facebook Places), when present |
location | raw object | Instagram's unmodified location payload that taggedPlace was parsed from |
like_count / comment_count | 183421 / 942 | Engagement counts, only present when includeEngagement is on |
play_count / view_count | 52000 | View counts on video posts, only present when includeEngagement is on |
video_versions / video_duration | array / 14.3 | Video renditions and duration, only present when includeVideoMetadata is on |
totalPostsScanned | 30 | On locationSummary rows: how many posts this run scanned for the profile |
geotaggedPostCount | 6 | On locationSummary rows: how many of those were geotagged |
geotaggedCoverage | 0.2 | On locationSummary rows: geotaggedPostCount / totalPostsScanned |
topTaggedPlaces | array of {placeName, postCount, lat, lng, city, address} | On locationSummary rows: the profile's most-tagged places, ranked by post count |
Tagged-place and roll-up data
taggedPlace is the structured version of whatever Instagram's raw location object carries on a geotagged post: a place ID, name, coordinates, address, and city, plus an externalId when Instagram links the place to an external directory such as Facebook Places. It is null whenever the post has no tagged place — never guessed or backfilled. When topPlacesPerProfile is greater than 0, each profile also gets one extra locationSummary row: totalPostsScanned and geotaggedPostCount for that run, the resulting geotaggedCoverage ratio, and topTaggedPlaces — that profile's most-tagged places ranked by how many scanned posts carried them, each with its own coordinates and city for mapping.
Targeting and segmentation fields
Three fields drive filtering: taken_at is what dateFilterType/filterDate compare against to keep only recent posts; hasLocation is the boolean the onlyGeotagged toggle filters on; scraped_username ties every row (post or summary) back to the profile it came from when you're running multiple profiles in one call and need to split results downstream.
Why not build this yourself?
Instagram's official Graph API and Basic Display API only expose an account's own content to that account's own access token — neither lets a third party pull an arbitrary public profile's posts or tagged-place data in bulk. Building that yourself means reverse-engineering the private feed endpoint: extracting a fresh app_id/csrf_token pair from the profile's public HTML, paging with max_id/next_max_id until more_available goes false, retrying failed requests, and switching from a datacenter to a residential proxy session when a fetch comes back empty. This Actor implements exactly that (get_tokens, fetch_page, and the proxy switch inside scrape_profile), so a run is one API call instead of a scraper you maintain yourself.
How to use data extracted from Instagram?
Travel and hospitality marketing
Run the Actor against a set of destination or venue accounts with onlyGeotagged on and topPlacesPerProfile set to a useful number. Each profile comes back with only its geotagged posts — taggedPlace.lat/lng ready to drop on a map — plus one locationSummary row listing the places that account tags most often, which is the fastest way to see where a creator's audience actually associates them with being.
Marketing and social-media agencies
Agencies running the same audit for several clients or competitors repeatedly can point the Actor at a rolling dateFilterType=relative / filterDate=30d window each month, then compare geotaggedCoverage across accounts to see which ones are actively geotagging content and which have stopped, without opening a single post by hand.
Market research and location intelligence
Aggregating taggedPlace.city, lat, and lng across many profiles' locationSummary rows shows where geotagging activity for a set of accounts clusters — useful for expansion research or spotting which neighborhoods a creator segment associates with most, fed straight into a heat-map or GIS tool from the JSON coordinates.
AI agents and automated pipelines
post_url, taggedPlace, and hasLocation are enough to ground an agent's answers in real, geotagged Instagram content — for example a location-recommendation tool that only surfaces posts Instagram's own location data confirms were taken at the place in question, called on demand through the Apify API.
⬇️ Input sample
All parameters are optional — the schema has no required fields, though profileUrls (or the legacy startUrls) must resolve to at least one entry or the run exits with no data.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
profileUrls | No | array | Instagram profile URLs, bare usernames, or post shortcodes; type is auto-detected. If both profileUrls and startUrls are set, profileUrls wins. | ["https://www.instagram.com/natgeo/"] |
startUrls | No | array | Legacy alias of profileUrls, kept so existing base-scraper input JSON keeps working. | ["natgeo"] |
postsPerProfile | No | integer | How many of each profile's most recent posts to scan for tagged-place data. Min 1, max 1000. No schema default; the UI prefills 10 and the Actor falls back to 10 when omitted. postsPerProfile wins over maxPosts if both are set. | 50 |
maxPosts | No | integer | Legacy alias of postsPerProfile. Min 1, max 1000. | 50 |
onlyGeotagged | No | boolean | ON: skip posts with no tagged place and keep scanning until postsPerProfile geotagged posts are found (or the scan runs out). OFF: return every scanned post. Default false. | true |
topPlacesPerProfile | No | integer | How many of a profile's most-tagged places to list in its roll-up row. Min 0, max 50. Set to 0 to skip the roll-up row. No schema default; the UI prefills 5 and the Actor falls back to 5 when omitted. | 5 |
dateFilterType | No | string | "absolute" or "relative". Default "relative". | "relative" |
filterDate | No | string | Absolute mode: YYYY-MM-DD. Relative mode: a value like 7d, 2w, 3m, 1y. Default "" (no filter). | "30d" |
includeEngagement | No | boolean | Keep like/comment/view-count fields on each post row. Default false. | true |
includeVideoMetadata | No | boolean | Keep video duration, quality-variant, and codec fields on each post row. Default false. | false |
proxyConfiguration | No | object | Apify Proxy configuration for every request this run makes. Defaults to the RESIDENTIAL group when left unset. | { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] } |
{"profileUrls": ["https://www.instagram.com/natgeo/"],"postsPerProfile": 30,"onlyGeotagged": true,"topPlacesPerProfile": 5,"dateFilterType": "relative","filterDate": "90d","includeEngagement": true,"includeVideoMetadata": false,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
⚠️ Common pitfall: filterDate's format has to match the dateFilterType you picked. The input schema's own pattern accepts both an absolute date and a relative value regardless of which mode is selected, so setting dateFilterType to "absolute" while typing a relative value like "30d" passes validation — but the Actor then tries to parse it as an ISO date, fails silently, and applies no date filter at all instead of raising an error. Match the two fields to the mode you actually chose.
⬆️ Output sample
Output is typed, normalized JSON with a consistent schema across every profile — one array of post rows interleaved with one locationSummary row per profile (when topPlacesPerProfile is greater than 0). Download it from the dataset as JSON, CSV, or Excel, or pull it through the Apify API.
[{"type": "post","isSummary": false,"hasLocation": true,"code": "DO8fSwLiNU-","short_code": "DO8fSwLiNU-","post_url": "https://www.instagram.com/p/DO8fSwLiNU-/","scraped_username": "natgeo","taken_at": 1758631325,"scraped_at": 1758631400,"like_count": 183421,"comment_count": 942,"taggedPlace": {"placeId": "212988663","placeName": "Yellowstone National Park","lat": 44.4279,"lng": -110.5885,"address": null,"city": "Yellowstone National Park","externalId": null},"location": {"pk": 212988663,"name": "Yellowstone National Park","lat": 44.4279,"lng": -110.5885,"city_name": "Yellowstone National Park","external_id": null,"facebook_places_id": null}},{"type": "locationSummary","isSummary": true,"scraped_username": "natgeo","scraped_at": 1758631400,"totalPostsScanned": 30,"geotaggedPostCount": 6,"geotaggedCoverage": 0.2,"topTaggedPlaces": [{"placeName": "Yellowstone National Park","postCount": 2,"lat": 44.4279,"lng": -110.5885,"city": "Yellowstone National Park","address": null}]}]
How do you filter and target specific posts?
This Actor's targeting comes down to three real axes, not a category or keyword search — input is always a profile, username, or shortcode.
- Date scope —
dateFilterTypechooses absolute (filterDate="2026-01-01") or relative (filterDate="30d") mode; posts older than the cutoff are dropped while scanning, so narrowing the window also reduces run time. - Quality threshold —
onlyGeotaggedis the actor's precision filter: instead of returning whatever the feed hands back, it keeps scanning further pages specifically until it haspostsPerProfileposts that actually carry a tagged place. - Volume control —
postsPerProfilecaps how many posts count toward the target per profile, andtopPlacesPerProfilecaps how many places appear in the roll-up. WhenonlyGeotaggedis on and geotagged posts are sparse for an account, the scan stops after 200 pages regardless of whether the target was reached — the run log reports how many were found before the cap hit.
{ "profileUrls": ["https://www.instagram.com/natgeo/"], "dateFilterType": "relative", "filterDate": "30d", "postsPerProfile": 40 }
{ "profileUrls": ["https://www.instagram.com/natgeo/"], "onlyGeotagged": true, "postsPerProfile": 20, "topPlacesPerProfile": 10 }
{ "profileUrls": ["https://www.instagram.com/natgeo/", "https://www.instagram.com/nasa/"], "postsPerProfile": 100, "topPlacesPerProfile": 0 }
▶️ Want to try other Instagram scrapers?
| Scraper | What it extracts |
|---|---|
| Instagram Story Details Scraper With Media Details | Story details per profile, normalized video/image renditions |
| Instagram Profile Post Scraper With Engagement Analytics | Profile posts plus per-post and profile-level engagement-rate analytics |
| TikTok User Profile Scraper: Business Leads | TikTok creator/business profiles with bio-parsed contact fields |
| Snapchat User Stories Scraper With Creator Profile Insights | Snapchat Stories, Highlights, and creator profile analytics |
How to extract Instagram data programmatically
Every run is a standard Apify Actor call: one run-sync/run request with your JSON input, structured JSON back from the dataset.
Python example
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("instagram-posts-scraper-with-tagged-places-and-coordinates").call(run_input={"profileUrls": ["https://www.instagram.com/natgeo/"],"onlyGeotagged": True,"postsPerProfile": 20,"topPlacesPerProfile": 5,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item.get("type") == "post":place = item.get("taggedPlace") or {}print(item["post_url"], place.get("placeName"), place.get("lat"), place.get("lng"))
Export to spreadsheets or CRM
Download the dataset as CSV directly from the Apify Console, or via the API's dataset/{id}/items?format=csv endpoint. Map post_url, scraped_username, taggedPlace.placeName, taggedPlace.lat, and taggedPlace.lng to spreadsheet columns for a location list you can drop straight into a mapping tool or CRM.
⚖️ Is it legal to scrape Instagram?
Scraping publicly visible Instagram posts is generally lawful — these are posts their creators chose to make public, and this Actor never accesses private accounts or bypasses a login wall. Because a scraped post row carries an identifiable creator (scraped_username) and, when geotagged, a real-world location tied to that person's activity, GDPR and CCPA can apply to how you store and use it depending on your jurisdiction and use case. Instagram's Terms of Service also govern automated access separately from data-protection law. Consult legal counsel for commercial applications involving bulk storage of personal data.
❓ FAQ
What happens if a post is deleted after I scrape it?
The Actor has no deletion-detection flag — a row reflects exactly what Instagram's feed returned at the moment of the run, timestamped by scraped_at. Re-run the Actor against the same profile to get the current state; a post that has since been deleted or made private will simply no longer appear.
Can I get engagement metrics along with tagged-place data?
Yes — set includeEngagement to true and each post row keeps like_count, comment_count, play_count, view_count, and related engagement fields alongside taggedPlace. It's off by default, so engagement fields are stripped from the row unless you turn it on.
How accurate is the tagged-place data?
The Actor returns Instagram's own location object exactly as attached to the post — it never infers or backfills a place. Accuracy depends on whether the creator tagged the correct place at posting time; Instagram's place database, not this Actor, is the source of the coordinates and address.
How many posts can I get per run?
Up to postsPerProfile per profile, capped at 1000 by the input schema. When onlyGeotagged is on, the scan for that profile also stops after 200 feed pages even if the target hasn't been reached — the run log reports how many geotagged posts were found before the cap.
How does the Only Geotagged Posts filter work?
With onlyGeotagged on, the Actor keeps requesting further pages of a profile's feed and discards any post without a tagged place, stopping once it has postsPerProfile geotagged posts, the date filter cuts it off, or the 200-page scan cap is hit. With it off, every scanned post is kept, geotagged or not.
Does this work with Claude, ChatGPT, and AI agent frameworks?
It runs as a standard Apify Actor reachable over the Apify API, so any agent framework that can make an HTTP call or use the apify-client package can trigger a run and read the resulting dataset — there is no dedicated MCP server documented for this Actor.
Can I use it without an Instagram account or login?
Yes. No sessionId or Instagram credentials are required anywhere in the input — the Actor only needs profileUrls/startUrls and, optionally, proxyConfiguration.
What's the difference between profileUrls/postsPerProfile and startUrls/maxPosts?
startUrls and maxPosts are legacy field names kept so input JSON built for the base Instagram Posts Scraper still runs unchanged. profileUrls and postsPerProfile are the current names; if both a current and legacy field are set, the current one wins.
Conclusion
Instagram Posts Scraper With Tagged Places & Coordinates turns a plain post export into structured, mappable location data — every post carries a hasLocation flag and a parsed taggedPlace object instead of Instagram's raw, undocumented location payload, and a per-profile roll-up surfaces a creator's most-tagged places without any manual counting. It's built for travel and hospitality marketers, agencies auditing multiple accounts, and researchers mapping geotagging activity across profiles. Run it from the Apify Console or trigger it through the API with profileUrls and onlyGeotagged set to get straight to geotagged results.