# Instagram Location Scraper: posts with coordinates

Instagram Location Scraper reads any Instagram place page and returns the geotagged posts on it, each carrying the venue’s name, city and coordinates.

[Run this scraper free](https://apify.com/apidojo/instagram-location-scraper)

[See the three jobs](#jobs)

apidojo/instagram-location-scraper

**Posts**

Estimated run cost

$0.00

Free Apify plan: 5 runs a month, 10 items a run. No credit card.

**$0.50** per 1,000 posts, flat

**100–200/s** posts, per the listing

**1.40M** runs all time · 1,911 users

**5.0 / 5** from 10 Apify reviews

Read on 21 September 2026.

## How do you name a place, and how far back?

Two inputs identify a place and neither carries a fee of its own, because this actor charges only for what it returns. A third input sets how far back the run reaches, and it is the only real cost control you have.

-   `startUrls`

    no feebilled per post only

    Pay per result

    You have the place page. Instagram’s explore/locations/ URL, city slug and all.

    `instagram.com/explore/locations/213131048/berlin-germany/`

-   `locationIds`

    no feebilled per post only

    Pay per result

    You hold numeric place IDs already. Cheapest to store, and what a batch run takes.

    `213385402`

-   The input that decides the bill

    `until`

    YYYY-MM-DDposts on or after

    Your real cost control

    Stops the run at a date. On a busy venue this is what stands between you and years of history.

    `2026-06-01`

-   `maxItems`

    ÷ $0.0005budget to item cap

    Hard stop

    A hard ceiling on posts returned. Budget divided by $0.0005 is the number to put here.

    `2000`

There is no query fee to weigh against volume here, which makes the arithmetic simpler than on the sibling scrapers and the date filter more important: nothing else caps a place with years of posts on it.

**Apify actor:** apidojo/instagram-location-scraper

**Inputs:** startUrls · locationIds · until · maxItems · customMapFunction

**Billing:** Pay per result. $0.0005 a post, no query fee and no free allowance

**Returns:** One record per geotagged post, with coordinates on every one

**Place identity:** location.id, name, city, lat and lng

**Date window:** until (YYYY-MM-DD), posts created on or after it

**Login or proxy:** Neither. Public place pages only

**Reliability:** 99.96% of 23,773 runs succeeded in the last 30 days

## What can you pull from a place?

Three shapes of run cover almost everything this actor is used for: read one venue in full, sweep a list of places in a single run, or bound a place to the window an event occupied.

**01 Map one venue $0.50 / 1,000 posts**

**02 Sweep a city No per-place charge**

**03 Bound an event You pay for the window only**

### How do you scrape the posts tagged at one place?

Paste the place page into startUrls. Every post tagged there comes back with the venue’s coordinates attached, billed at $0.0005 each with nothing else added. Two thousand posts cost $1.00.

Input

```
{
  "startUrls": [
    "https://www.instagram.com/explore/locations/213131048/berlin-germany/"
  ],
  "maxItems": 2000
}
```

2,000 × $0.0005 \= **$1.00**

What comes back

The **geotagged post**, The post, its author, and the place, including latitude and longitude.

```
{
  "type": "post",
  "code": "ABCdefGhIjK",
  "url": "https://www.instagram.com/p/ABCdefGhIjK/",
  "createdAt": "2026-01-15T10:20:30.000Z",
  "likeCount": 123,
  "commentCount": 45,
  "isPaidPartnership": false,
  "location": {
    "id": "555555555",
    "name": "Example Place",
    "city": "Sample City, Country",
    "lat": 40.7128,
    "lng": -74.006
  }
}
```

A busy venue has more history than you want to buy

Nothing stops a popular place from returning years of posts, and every one of them is billable. Set maxItems, or set until, before the first run rather than after reading the invoice.

### How do you scrape several Instagram locations at once?

Put the numeric place IDs into locationIds. One run covers the whole list, and because there is no per-place fee, forty venues cost exactly what forty venues’ worth of posts cost, no more.

Input

```
{
  "locationIds": [
    "213385402", "213131048", "555555555"
  ],
  "maxItems": 3000
}
```

3,000 × $0.0005 \= **$1.50**

What comes back

The **geotagged post**, location.id tells you which place each record belongs to, so one dataset splits.

```
{
  "location": { "id": "213385402", "name": "Mitte, Berlin" },
  "owner": {
    "username": "example_user",
    "fullName": "Example User",
    "isVerified": true,
    "isPrivate": false
  },
  "isCarousel": false,
  "isVideo": true
}
```

IDs are stable, URLs are not always

Instagram’s place URL carries a slug after the ID, and slugs get rewritten. The numeric ID is the durable identifier, which is why a saved list of places is worth storing as locationIds rather than as links.

### How do you scrape a venue for one date range?

Set until to the date the window opens and the run returns only posts created on or after it. For a festival, an opening or a conference, that turns an entire venue history into the few days you care about.

Input

```
{
  "startUrls": [
    "https://www.instagram.com/explore/locations/213131048/berlin-germany/"
  ],
  "until": "2026-06-01",
  "maxItems": 5000
}
```

posts since the date × $0.0005 \= **From $0.00**

What comes back

The **geotagged post**, createdAt is the field the filter works on, and it is on every record.

```
{
  "createdAt": "2026-06-14T19:41:02.000Z",
  "likeCount": 2841,
  "commentCount": 96,
  "caption": "Closing set. #berlin",
  "audio": {
    "title": "Example Track",
    "artist": "Example Artist",
    "duration": 180000
  }
}
```

until has no upper bound

It sets a floor, not a range: everything newer than the date comes back. To bound both ends, filter on createdAt after the run, or schedule the run to finish while the window is still the newest thing on the place.

## What does a geotagged post carry?

One record per post, and the part that matters here is the place: every record carries the venue’s ID, name, city and coordinates, which is what makes the output joinable against a map rather than merely readable.

-   5

    The place

    location, on every record

    -   location.id, the stable identifier
    -   location.name
    -   location.city
    -   location.lat
    -   location.lng
-   8

    The post

    Always present

    -   id, code, url
    -   createdAt
    -   caption
    -   likeCount, commentCount
    -   isPaidPartnership, isPinned
-   6

    Who posted it

    owner, plus coowners on collabs

    -   owner.username, owner.id
    -   owner.fullName
    -   owner.profilePicUrl
    -   owner.isVerified, isPrivate
    -   coowners\[\] on collab posts
-   4

    What it is

    Depends on the post type

    -   isVideo, isCarousel
    -   video{ url, duration }
    -   image{ url, width, height }
    -   audio{ title, artist, duration }

**location.id:** Numeric place ID. The durable way to store a venue

**location.name:** Venue name as Instagram displays it

**location.city:** City and country string

**location.lat · lng:** Coordinates. What makes the output mappable

**code · url:** Shortcode and permalink for the post

**createdAt:** Publish time, ISO 8601. What until filters on

**caption:** Caption text, hashtags and mentions as written

**likeCount · commentCount:** Engagement at the time of the run

**isLikeAndViewCountsDisabled:** True where the author hid their counts

**isPaidPartnership:** Instagram’s paid-partnership flag

**owner:** id, username, fullName, profilePicUrl, isPrivate, isVerified

**coowners:** The other accounts on a collab post

**isVideo · isCarousel:** Which of the three post types this is

**video · image:** Media URLs with dimensions, and duration on video

**audio:** Track title, artist, cover art and duration where a post has one

customMapFunction runs over each record on the way out, so you can flatten location into top-level columns before the data ever reaches a spreadsheet. Transformation only, using it to drop records is grounds for an automatic ban.

## Where location data runs out

Five things bound what a place page can tell you. Four are Instagram’s doing and one is simply how geotagging works in practice.

-   01

    Only posts the author geotagged

    A place page lists what people chose to tag there. Posts taken at the venue without a tag are invisible to it, and always will be.

-   02

    The tag is a claim, not a measurement

    Anyone can tag any place from anywhere. Coordinates come from the venue record, not from the device, so treat them as where the post says it is.

-   03

    Place IDs outlive place URLs

    The slug after the ID in an explore/locations/ URL can be rewritten. Store locationIds if the list has to survive.

-   04

    until sets a floor, not a range

    Everything created on or after the date comes back. There is no matching upper bound, so cap the far end with maxItems or filter createdAt afterwards.

-   05

    Public posts only, and counts can be hidden

    No login and no cookies, so private accounts never appear. Authors can also hide likes and views, and those records arrive with isLikeAndViewCountsDisabled set.

Demo mode on a free Apify account allows 5 runs a month, 10 items in each.

## Flat rate: what the posts cost

There is one number. Every post returned costs $0.0005, so a thousand cost $0.50 and ten thousand cost $5.00, the same whether they came from one venue or forty, because nothing is charged for naming a place.

| Run | Method | Calculation | Cost |
| --- | --- | --- | --- |
| 100 posts | 1 place | 100 × $0.0005 | $0.05 |
| 1,000 posts | 1 place | 1,000 × $0.0005 | $0.50 |
| 10,000 posts | 1 place | 10,000 × $0.0005 | $5.00 |
| 3,000 posts | 3 places | 3,000 × $0.0005 | $1.50 |
| 20,000 posts | 40 places | 20,000 × $0.0005 | $10.00 |
| 2,000 posts a week | 1 place, scheduled | 52 × 2,000 × $0.0005 | $52.00 |

Computed from the single charge event the Apify Store API reports for this actor: $0.0005 per dataset item, with no query event and no included allowance. Its three sibling scrapers all bill a query fee with items thrown in, so none of their arithmetic carries over to this one.

## Who needs geotagged Instagram data?

Five kinds of work depend on knowing where a post was tagged rather than who wrote it: location marketing, venue and property research, event measurement, lead generation and open-source investigation.

-   Local and location marketing

    Map one venue, monthly

    See who posts from a catchment area and what they photograph, then aim campaigns at the places that actually generate content

    $0.50 per 1,000 posts

-   Venue and property research

    Sweep a city

    Compare footfall signals between sites by how much tagged content each one produces

    $10.00 per 40 places

-   Event and festival teams

    Bound an event

    Measure a festival by the posts tagged at its venue inside its own dates, not a whole year of them

    Window only, from cents

-   Lead generation

    Sweep a city, filtered on owner

    Build lists of accounts active in a specific area, with the venue that surfaced each one attached

    $1.50 per 3,000 posts

-   OSINT and investigative research

    Map one venue, with until

    Establish what was publicly posted from a place across a defined period, coordinates included

    $5.00 per 10,000 posts

## Running it from your own code

The actor is apidojo/instagram-location-scraper. Because it is pay per result there is no query arithmetic to do in code: the cost of a run is maxItems × $0.0005, which you can set from a budget before you call it.

**Python**

**JavaScript**

**cURL**

```
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

BUDGET = 2.50            # dollars
cap = int(BUDGET / 0.0005)   # 5,000 posts

run = client.actor("apidojo/instagram-location-scraper").call(run_input={
    "startUrls": [
        "https://www.instagram.com/explore/locations/213131048/berlin-germany/"
    ],
    "until": "2026-06-01",
    "maxItems": cap,
})

for post in client.dataset(run.default_dataset_id).iterate_items():
    loc = post["location"]
    print(loc["lat"], loc["lng"], post["createdAt"], post["owner"]["username"])
```

```
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

// Several places, one run. No per-place charge, so the list can be long.
const run = await client.actor('apidojo/instagram-location-scraper').call({
  locationIds: ['213385402', '213131048'],
  maxItems: 3000,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();

// location.id is the stable key to group on; slugs in URLs are not.
const byPlace = Object.groupBy(items, (p) => p.location.id);
for (const [id, posts] of Object.entries(byPlace)) {
  console.log(posts[0].location.name, id, posts.length, 'posts');
}
```

```
curl -X POST \
  "https://api.apify.com/v2/acts/apidojo~instagram-location-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"locationIds":["213385402"],"until":"2026-06-01","maxItems":1000}'
```

Datasets download as CSV or stream over the API. If a spreadsheet is the destination, flatten location.lat and location.lng with customMapFunction first, nested objects and CSV columns do not get along.

## Instagram Location Scraper FAQ

### How much does Instagram Location Scraper cost?

It is pay per result: $0.0005 a post, which is $0.50 per 1,000. There is no query fee and no free allowance, so a run costs exactly what it returns.

### Does it return latitude and longitude?

Yes. Every record carries location.lat and location.lng alongside the venue name, city and numeric ID, which is what lets the output be joined to a map or a catchment area.

### Should I use the place URL or the location ID?

Either works and neither costs more. The numeric ID is the one to store, because Instagram can rewrite the slug that follows it in a place URL.

### Can I limit a run to recent posts?

Give until a YYYY-MM-DD date and the run stops once it reaches posts older than it. That is a floor and not a range, so pair it with maxItems when the far end matters too.

### Does it find posts taken at a place but not tagged there?

No, and nothing can. A place page lists what authors chose to tag. Untagged posts are not associated with the venue at all.

### Are the coordinates where the photo was taken?

They are the venue’s coordinates from Instagram’s place record, not the device’s. A tag is a claim about location, and anyone can tag any place from anywhere.

### How many places can one run cover?

As many as you list in locationIds. Nothing is charged for naming a place, so the practical limit is the posts you are willing to pay for, not the number of venues.

### Can I try Instagram Location Scraper for free?

Demo mode on a free Apify account gives 5 runs a month at 10 items each with no card, which is enough to confirm a place page returns what you expect.

## Where Instagram Location Scraper fits

[Parent scraper Instagram Scraper Six URL types in one actor at $0.49 per 1,000 posts, location among them. Use it when a single run has to mix places with profiles or tags. This one reads places only, and is the actor to schedule when a place is the whole question.](/scrapers/instagram-scraper/)

Sibling scrapers

-   [Instagram Profile Scraper](/scrapers/instagram-user-scraper/)
-   [Instagram Hashtag Scraper](/scrapers/instagram-hashtag-scraper/)
-   [Instagram Comments Scraper](/scrapers/instagram-comments-scraper-api/)

Guides

-   Turning tagged posts into a catchment map*Coming soon*
-   Measuring an event by its venue, not its hashtag*Coming soon*
-   Why Instagram place IDs beat place URLs*Coming soon*

## Point it at one place

Fifty cents buys a thousand posts, coordinates and all.

`locationIds: ["213385402"] · until: "2026-06-01"`

[Run this scraper free](https://apify.com/apidojo/instagram-location-scraper)

Apidojo is not affiliated with Meta Platforms, Inc.
