Instagram Location Scraper - Posts by Place, Top and Recent avatar

Instagram Location Scraper - Posts by Place, Top and Recent

Pricing

from $0.38 / 1,000 results

Go to Apify Store
Instagram Location Scraper - Posts by Place, Top and Recent

Instagram Location Scraper - Posts by Place, Top and Recent

Instagram location scraper: posts by location ID or place URL. A place page has two feeds, Top and Recent, holding different posts, and you get both. Each row has the caption, likes, comments, media URLs, owner, timestamp and place id. About 70 posts per place. $0.40 per 1,000 posts.

Pricing

from $0.38 / 1,000 results

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

22

Total users

10

Monthly active users

2 days ago

Last modified

Categories

Security

Limited permissions

Share

Instagram location scraper for a place id, the posts tagged there as rows: caption, like and comment counts, image and video links, the poster, the timestamp, the place name and the place id each row came from. A place page has a Top feed and a Recent feed holding different posts, and you get both.

A place feed is a sample, not an archive: about 70 posts per place, whatever you set the limit to. On the free Apify plan a run may stop after one page, about 24 posts, and a free row says so.

InputLocation IDs, /explore/locations/ URLs, or a place's name (paid add-on)
OutputOne row per post: caption, likes, comments, image and video links, poster, timestamp, place name and id
Ceiling2,000 posts per run, and about 70 per place
Account neededNone
Price$0.40 per 1,000 posts on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 12,500
Using an AI agent?
Actordami_studio/instagram-location-scraper
Set one fieldlocationIds, labelled "Location IDs" in the Console
Cap the billmaxTotalChargeUsd on the run, for example 0.10: it never charges past that
MCP, one linkhttps://mcp.apify.com/?tools=fetch-actor-details,dami_studio/instagram-location-scraper
How oftenDaily, for new posts from a place

🔍 What Instagram Location Scraper does

You give it places, it returns what people tagged there. Photos, videos and carousels all come back in the same row shape. Every row carries the locationId you asked for, so a multi-place run stays separable. You don't need an Instagram account.

Finding the id takes ten seconds: take the number out of instagram.com/explore/locations/212988663/.

Filters keep a run to a date, to photos or videos, or to a number of posts per place. The place details row adds each place's post count, category, address and coordinates, free.

📋 What data you get from each Instagram location post

What you getField
What the post is: a photo, a video or a carouseltype, productType, isVideo
Link and shortcodeurl, shortCode
Caption, and the hashtags and handles in itcaption, hashtags, mentions
Likes, comments and video views, and whether likes are hidden or comments offlikesCount, commentsCount, videoViewCount, likesHidden, commentsDisabled
Cover image, video file, every carousel frame and the image sizedisplayUrl, videoUrl, images, dimensions
Video length in secondsvideoDuration
Who posted it, the accounts tagged in it, and whenownerUsername, ownerFullName, ownerId, taggedUsers, timestamp
The sound on a reel, and a link to itaudioTitle, audioArtist, isOriginalAudio, audioUrl
Paid partnership, sponsors and co-authorsisPaidPartnership, sponsors, coauthors
Instagram's alt textaccessibilityCaption
Which of your places it came from, and the spot it is tagged atlocationId, locationName
On a place found by name, the name you typed and the place it landed onsearchTerm, placeName
Comments, when the comments add-on is ontopComments
One row per place, when you ask for itrecordType: "place" rows

▶️ How to scrape Instagram posts by location

  1. Open the place on Instagram and copy the number out of instagram.com/explore/locations/<id>/.
  2. Open Instagram Location Scraper and click Try for free.
  3. Paste the number into Location IDs, or the whole URL into Location URLs.
  4. Set Max posts. Start at 20 while you look at the output shape.
  5. Click Start, then download the dataset as JSON, CSV or Excel.

Give it at least one place. With nothing in either field you get one uncharged BAD_INPUT row, not a failed run.

💰 How much does it cost to scrape Instagram posts by location?

$0.40 per 1,000 posts on the Free plan. Paid plans pay a little less: $0.395 on Starter, $0.39 on Scale and $0.385 on Business. On the free plan, the $5 Apify gives you each month covers about 12,500 posts. On the free plan a run may stop after one page and say so in a free row; a paid plan gets the full run.

You pay per post delivered, and a post found in both tabs is billed once. Diagnostic rows, posts your filters leave out and the place details row are free.

Two paid add-ons, billed only when used. Finding places by name costs $0.005 for each name that finds a place on the Free plan, $0.004938 on Starter, $0.004875 on Scale and $0.004812 on Business. A name that matches no place isn't charged. Comments in the post rows cost $0.40 per 1,000 comments on the Free plan, $0.395 on Starter, $0.39 on Scale and $0.385 on Business.

📥 What you give it

{
"locationIds": ["212988663"],
"resultsLimit": 50,
"newerThan": "7 days",
"includePlaceDetails": true
}
FieldDefaultWhat it is
locationIdsnoneThe number out of /explore/locations/<id>/. Numeric ids only.
startUrlsnoneOr paste the /explore/locations/… URLs. Either works, and you can mix them.
searchTermsnonePaid add-on: place names to look up, up to 10 a run. Add the city or country if you know it. A free row gives you the name and coordinates of the place it picked, so you can check them. If it picked the wrong one, add more of the name or give the id. If nothing matches you get one free row, no posts and no charge.
placesPerTerm1How many of the places that match a name to read, 1 to 10, the likeliest first. A name can match fewer.
resultsLimit50Posts for the whole run, not per place, 1 to 2,000. This is also your spend cap.
maxPostsPerPlacenoneStop each place at this many posts, 5 to 2,000, so later places get read too.
newerThannoneOnly posts from this day on (2026-10-01) or within a window (7 days), in UTC. Reads only the Recent feed, since Top is ranked, not dated.
postTypesallall, photos (photos and carousels) or videos (videos and reels). videos reads only the Recent feed, where nearly all of them are.
includePlaceDetailsfalseOne free row per place with its own details.
commentsPerPostnonePaid add-on: up to this many comments in each post's row, up to 15. Set it to 12 or more. Posts with only a few comments come back without them, and no comments are charged for those.
sessionCookiesnoneOptional: your own session, if you would rather the run read through your account. It is used only for your run, and you are responsible for using it within the site's terms.
proxyConfigurationnoneOptional. Servers of your own are used exactly as given.
notionConnector, notionParentIdnoneOptional. Write each post into a Notion data source as well as the dataset.

An entry that is not a number is dropped. Several places are filled in order until resultsLimit is spent, so put the one you care about most first, or set maxPostsPerPlace. A value the run cannot use, such as a date written as "yesterday", stops it before anything is read, with a free row naming it.

📤 What you get back

Real run output

A real row from a run on 17 October 2026, with the long image links trimmed and the poster replaced by a stand-in:

{
"ok": true,
"type": "carousel",
"shortCode": "DemdUGzjZxx",
"url": "https://www.instagram.com/p/DemdUGzjZxx/",
"caption": "Finally made it to the famous Katz’s deli!!!!!",
"hashtags": [],
"mentions": [],
"likesCount": 3,
"commentsCount": 0,
"videoViewCount": 0,
"displayUrl": "https://scontent-ord5-1.cdninstagram.com/v/t39.30808-6/...",
"videoUrl": null,
"images": [
"https://scontent-ord5-1.cdninstagram.com/v/t39.30808-6/...",
"https://scontent-ord5-2.cdninstagram.com/v/t39.30808-6/..."
],
"isVideo": false,
"dimensions": {"height": 1474, "width": 1536},
"ownerUsername": "example_account",
"ownerId": "1234567890",
"timestamp": "2026-10-17T15:43:49.000Z",
"accessibilityCaption": null,
"locationId": "1721707",
"recordType": "post",
"locationName": "Katz's Delicatessen",
"productType": "carousel_container",
"videoDuration": null,
"ownerFullName": "Example Name",
"taggedUsers": [],
"audioTitle": null,
"audioArtist": null,
"isOriginalAudio": null,
"audioUrl": null,
"likesHidden": false,
"commentsDisabled": false,
"isPaidPartnership": false,
"sponsors": [],
"coauthors": [],
"topComments": null
}

And the place details row from the same run:

{
"ok": true,
"recordType": "place",
"locationId": "1721707",
"locationName": "Katz's Delicatessen",
"url": "https://www.instagram.com/explore/locations/1721707/",
"postCount": 248386,
"category": "Deli",
"address": "205 E Houston St",
"city": null,
"zip": null,
"latitude": 40.72222,
"longitude": -73.98751,
"phone": null,
"website": null,
"facebookPlaceId": "89033874836"
}
FieldHow to read it
locationIdWhich of your places produced this row.
locationNameThe spot the post is tagged at. For a city or an area, Top often holds posts tagged at places inside it.
searchTerm, placeNameOnly on rows from a place found by name: the name you typed and the place the run took for it.
shortCodeUnique per post. Use it as your dedupe key across runs.
imagesEvery frame of a carousel, largest version. A single photo gives you one entry.
videoViewCount, videoUrl, videoDurationnull on stills, as above.
displayUrl, images, audioUrlSigned links that expire within hours. Download what you want to keep.
audioTitle, audioUrlFilled on reels that carry a sound. The link is Instagram's own; nothing is downloaded or kept by the run.
isPaidPartnership, sponsorsisPaidPartnership is Instagram's own flag. sponsors lists the brand accounts Instagram names on a paid partnership post. It stays [] on every other post, and on a paid one that names no brand.
topCommentsnull unless the comments add-on read the post.

🧾 Reading the output

Filter on recordType == "post" and you have your posts.

RowHow to spot itBilled
A postrecordType: "post" and a shortCodeyes
A place's details: postCount, category, address, city, zip, latitude, longitude, facebookPlaceId, and the phone and website the place lists, any of them null when not shownrecordType: "place"no
A place a name search picked: searchTerm, locationId, locationName, latitude, longituderecordType: "place_match"no, the search is
A diagnosticok: false and an errorCodeno
CodeWhat it means
NO_RESULTSThe place resolved and both tabs came back empty, nothing passed your filters, or a name found no place, with the name in searchTerm. For a name, check the spelling, add the city or give the id, or run it again in a minute.
NOT_SERVEDThis post was not served this run. Re-run it later. Runs before 13 October 2026 wrote BLOCKED here.
FREE_PLAN_LIMITYou are on the free Apify plan, so the run read only part of your input. locationsNotRead lists what it skipped. A paid plan gets the full run.
PARTIALSome posts arrived for that place, then the run stopped early. What arrived is correct.
NOT_FOUNDNo place answers to that id.
RATE_LIMITED, SERVER_ERROR, NETWORKInstagram was busy or unreachable. Run it again.
TIME_LIMITThe run stopped just before its time limit. The posts delivered are kept and charged. Give it more time, or ask for fewer posts, to get the rest.
BAD_INPUTAn option has a value the run cannot use. Nothing was read.
COMMENTS_PARTIALSome posts came without their comments. Only comments delivered were charged.
COMMENTS_OFFComments per post was set lower than the fewest comments a post needs to be read. Posts came without comments, and none were charged.
UNEXPECTED_ERRORThe run stopped early on an unexpected error. The results before this row are kept.

A diagnostic row does not fail the run, TIME_LIMIT included: a run the time limit stopped before any post came back still ends as succeeded, with an amber status message.

💡 What people use it for

  • Seeing what guests actually photograph at a venue before writing the brief for a shoot there.
  • Finding local creators who post at a place regularly.
  • Checking what a neighbourhood, festival or stadium looks like through its visitors' cameras.
  • Keeping a daily record of a place: set newerThan to 1 day and schedule the run.

What visitors say about a place, in three steps:

  1. Run this on the place id.
  2. Sort the rows on commentsCount and copy the url of the posts at the top.
  3. Paste those links into Instagram Comments Scraper and read the conversation under them.

🚧 What it does not do

  • About 70 posts per place. Setting the limit higher does not reach further in.
  • A place feed is a sample. Instagram decides what sits in Top and Recent.
  • Finding a place by name is a good guess, not a lookup. A common name can land on a namesake elsewhere, so check the coordinates on the place_match row, or give the id.
  • No private accounts, and no stories or highlights.
  • Comments come in Instagram's own order, not newest first, and not on posts with only a few. For a whole thread, use Instagram Comments Scraper.
  • No files are stored. audioUrl, videoUrl and the image links are Instagram's own, and expire within hours.
  • It is not an official Instagram tool. Dami's Studio is independent and is not affiliated with or endorsed by Instagram or Meta, or by any other company named on this page.

🧭 Which Instagram scraper do you need?

If you wantUse
Posts tagged at a placeThis one
Posts under a hashtagInstagram Hashtag Scraper
Everything one profile has postedInstagram Scraper
Bio and counts for the accounts posting thereInstagram Profile Scraper
One post or reel you have the link forInstagram Post Scraper
Comments under a postInstagram Comments Scraper

❓ Questions people ask

Where do I find the Instagram location ID?

In the address bar. Open the place on Instagram and take the number out of /explore/locations/<id>/. Or type the place's name in searchTerms, a paid add-on.

Do I need an Instagram account to scrape a location?

No. The cookie field is optional.

Why did I get fewer posts than I asked for?

Because the place had fewer available, or your filters left some out. The public tabs hold roughly 70 posts per place, and you are only billed for what arrived.

Is resultsLimit per place or per run?

Per run. Ask for 100 across three places and you get 100 posts in total, not 300. Set maxPostsPerPlace to share them out.

Why don't I get the same posts I see in the app?

The app shows you, signed in, a feed that shifts by the hour. Open the place in a private browser window: what a logged-out visitor sees there is what a run reads. Likes and comments are a snapshot at read time.

Can I call it from code or connect it to an AI assistant?

The API tab has code for Python, JavaScript and the CLI. MCP clients like Claude and ChatGPT use https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/instagram-location-scraper; coding assistants can load our skill file. All three bill your Apify account at the same price.

# pip install apify-client
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("dami_studio/instagram-location-scraper").call(
run_input={
"locationIds": ["212988663"],
"resultsLimit": 20,
},
max_total_charge_usd=0.10, # the most this run may spend
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row.get("ok") is False: # free note rows, not results
continue
print(row.get("timestamp"), row.get("url"))

This reads public posts only, never private accounts or messages. Results can still contain personal data, which GDPR, PIPEDA and similar laws cover, so keep only what you need. The place row can carry the phone number a business lists, and anti-spam laws such as CASL, the EU e-privacy rules and CAN-SPAM decide how anyone may be contacted. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the location ID you used and the run ID. The code on the diagnostic row usually explains it on its own.