# Instagram Location Scraper (Pay Per Result) (`apidojo/instagram-location-scraper`) Actor

Instagram Location Scraper, your premier solution for harvesting data from locations on Instagram. It offers remarkable value at just $0.50 per 1000 posts, with the capability to scrape between 100-200 posts per second!

- **URL**: https://apify.com/apidojo/instagram-location-scraper.md
- **Developed by:** [API Dojo](https://apify.com/apidojo) (community)
- **Categories:** Social media, Lead generation
- **Features:** Limited permissions
- **Stats:** 2,086 total users, 94 monthly users, 100.0% runs succeeded, 59 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.49 / 1,000 posts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Instagram Location Scraper: Your hawk-eye on Instagram Locations

Introducing the Instagram Location Scraper, your premier solution for harvesting data from locations on [Instagram.com](https://instagram.com). Renowned for its exceptional speed and thoroughness, this tool facilitates quick and comprehensive extraction of posts from any [Instagram.com](https://instagram.com) location. Ideal for researchers seeking in-depth data on [Instagram.com](https://instagram.com) locations or companies aiming to leverage geographical insights, the Instagram Location Scraper is the go-to resource. Additionally, it offers remarkable value at just **$0.50 per 1000 posts**, with the capability to scrape between **100-200 posts per second!**

### ℹ️ Disclaimer

We are professionals specializing in data extraction. This actor is exceptionally fine-tuned for scraping [Instagram](https://instagram.com), providing you with a comprehensive suite of tools. Moreover, we provide top-tier maintenance and exceptional support. Pure data - at your fingertips. You name it, we get it.

#### Important Note About Usage

This scraper is designed to collect posts from specific Instagram locations. Please make sure to follow these rules:

- The selected location should have **at least 10 posts** available. Using low-activity places leads to inefficient runs.
- Always set your `maxItems` value to **greater than 10** to ensure a proper data fetch.
- Scraping locations with too few posts may trigger our **rate-limiter** and can result in blocked requests.
- **Free users**: Limited to **5 runs per month**, each capped at **10 items**

### 🐉 Features and Functionality

- No Authentication needed. 🛡️
- Super cheap. **$0.50 per 1K results.** 💰
- No proxy needed. High flexibility, perfectly customized. 🐉
- Simple Output, extremely fast. ⚡️
- Lightning speed, extreme efficiency, and fits for all types of usage. 🚀
- Simple date filter for only including posts created on or after a date.

### 🆓 Demo Mode & Free Users

Users on the Free Plan can use the actor only in Demo Mode. **Free users can run the actor up to 5 times per month**, with each run capped at a maximum of 10 items — just enough to test it out. To use this actor without limitations, subscribe to a paid plan on Apify. [Subscribe here](https://apify.com/pricing?fpr=yhdrb).

### 👹 Competitors

There are no direct competitors of Instagram Location Scraper. All other scrapers on the market, uses it as a functionality rather than focusing only that part. Getting this data can be tough and it always requires a special care and maintenance. Therefore, Instagram Location Scraper is one and only at the current moment.

### 🎎 Who needs this?

The Instagram Location Scraper is engineered to deliver outstanding efficiency.

- **Marketing and Advertising Professionals:** Marketers and advertisers can use location data to analyze trends, hashtags, and the popularity of products or events in specific areas. This can help them tailor their campaigns to target audiences more effectively, understand competitor activities, and identify influencers who could amplify their message.
- **Lead Generation Experts:** With detailed insights into the interests and activities of people in specific areas, Lead Generation experts can design highly targeted advertising campaigns. This ensures that marketing efforts are directed toward individuals most likely to be interested in the product or service, improving conversion rates and ROI.
- **OSINT Professionals:** OSINT professionals can use location-based data to monitor and analyze trends, events, or activities in specific areas. This can be crucial for security assessments, investigative journalism, or research. Understanding the context and sentiment in a particular location can help in piecing together information that's not readily apparent, offering insights into political movements, cultural events, or security threats.
- **Real Estate Professionals:** Real estate agents and companies can use [Instagram.com](https://instagram.com) location data to understand the popularity and perception of different neighborhoods or properties. This insight can help in marketing properties more effectively, identifying areas with high potential for investment, or even guiding clients on the most Instagrammable spots to boost their property's appeal.
- **Retail and E-commerce:** Retailers and e-commerce businesses can leverage location-based insights from [Instagram.com](https://instagram.com) to understand where their products are being used or talked about the most. This can inform decisions on where to open new stores, what products to stock more of in certain locations, and how to create localized marketing campaigns that resonate with the community's preferences.

### 🍜 Output Example

```
{
  "type": "post",
  "id": "1234567890123456789",
  "code": "ABCdefGhIjK",
  "url": "https://www.instagram.com/p/ABCdefGhIjK/",
  "createdAt": "2025-01-15T10:20:30.000Z",
  "likeCount": 123,
  "commentCount": 45,
  "caption": "Example caption text with #hashtags and @mentions.",
  "isAvailable": true,
  "isLikeAndViewCountsDisabled": false,
  "isPinned": false,
  "isPaidPartnership": false,
  "isCarousel": false,
  "isVideo": true,
  "owner": {
    "id": "9876543210",
    "username": "example_user",
    "fullName": "Example User",
    "profilePicUrl": "https://example.com/profile.jpg",
    "isPrivate": false,
    "isVerified": true
  },
  "coowners": [
    {
      "id": "9876543212",
      "username": "example_user_2",
      "fullName": "Example User_2",
      "profilePicUrl": "https://example.com/profile2.jpg",
      "isPrivate": false,
      "isVerified": true
    }
  ],
  "location": {
    "id": "555555555",
    "name": "Example Place",
    "city": "Sample City, Country",
    "lat": 40.7128,
    "lng": -74.006
  },
  "video": {
    "id": "video_12345",
    "url": "https://example.com/video.mp4",
    "width": 1080,
    "height": 1920,
    "duration": 12.34
  },
  "image": {
    "url": "https://example.com/image.jpg",
    "width": 1080,
    "height": 1350"
  },
  "audio": {
    "id": "audio_98765",
    "title": "Example Track",
    "artist": "Example Artist",
    "coverArt": "https://example.com/cover.jpg",
    "duration": 180000,
    "audioUrl": "https://example.com/audio.mp4"
  }
}
```

### 🍚 Input Parameters

| Field | Type | Description | Default value
| ----- | ---- | ----------- | -------------|
startUrls | array | [Instagram](https://instagram.com) URLs. Paste the URLs and get the results immediately. Location URLs are supported. | `[]` |
locationIds | array | [Instagram](https://instagram.com) Location IDs. You can find the IDs from the location links. ID for `https://www.instagram.com/explore/locations/213131048/berlin-germany/` would be `213131048`. | `[]` |
maxItems | number | Maximum number of items that you want to receive as output | `Infinity` |
until | date | Date filter. Only include posts created on or after this date. | `"2025-01-01"` |
customMapFunction | string | JavaScript function to transform each output item. Ignored with a warning if it is not a usable function (see [Custom Map Function](#-custom-map-function)). | `null` |
outputConnector | string | MCP connector to deliver the results to — pick one (see [Send results straight into Notion, Todoist and more](#-send-results-straight-into-notion-todoist-and-more-mcp-connectors)). | `null` |
deliverTarget | string | Where the connector writes — paste the URL or ID (Notion example: `https://www.notion.so/My-Posts-24f8a1b2c3d44e5f8a9b0c1d2e3f4a5b`); some services need none. | `null` |
deliverMode | string | `perPost` (one record per scraped item) or `summary` (one roll-up per run). | `perPost` |
deliverMaxItems | number | Optional cap on how many records `perPost` delivers (ignored in `summary`). | `null` |

### 🧩 Custom Map Function

Transform output using the `customMapFunction` parameter. This JavaScript function receives each post object and returns your desired format-add engagement metrics, flatten owner or location data, or calculate custom analytics.

**Important:** Custom map function is for data transformation-**not for filtering**. Filtering items may result in automatic restrictions. Returning an empty object does not remove the item from the dataset-it is saved as `{ "noResults": true }` instead.

#### Example: Engagement and Location Flattening

```javascript
(object) => ({
  ...object,
  totalEngagement: (object.likeCount ?? 0) + (object.commentCount ?? 0),
  username: object.owner?.username,
  isVerified: object.owner?.isVerified,
  locationName: object.location?.name,
  locationCity: object.location?.city,
  video: undefined,
  image: undefined
})
```

#### Common Transformations

| Use Case                 | What to Add                                                  |
| ------------------------ | ------------------------------------------------------------ |
| **Engagement Analysis**  | `totalEngagement`, `likesToComments`, `performanceScore`     |
| **Owner Flattening**     | `username`, `fullName`, `isVerified`                         |
| **Location Flattening**  | `locationName`, `locationCity`, `lat`, `lng`                 |
| **Data Cleanup**         | Set `video: undefined`, `image: undefined`                   |

#### Requirements & Error Handling

The value must be a **single JavaScript function** that takes one item and returns the transformed item. Arrow functions and regular functions both work; `async` and generator functions are not supported.

**Limits:** the function runs in an isolated sandbox. It must be synchronous and finish within about 1 second per item, and only plain JavaScript is available (no network requests, `require` or `console`). Each item is passed in as plain JSON data.

**An unusable function never stops your run.** The actor logs a warning, ignores the function, and saves the original, unmodified items instead-so you still get your data:

| Situation | What happens |
| --------- | ------------ |
| Not valid JavaScript (for example, plain text pasted into the field) | Rejected before the first request; original items are saved |
| Valid JavaScript but not a function (for example, an object) | Rejected before the first request; original items are saved |
| `async` or generator function | Rejected before the first request; original items are saved |
| Returns a Promise (for example, `(object) => Promise.resolve(object)`) | Rejected at that point; the remaining items are saved unmodified |
| Returns something other than an object (for example, a number or `null`) | Rejected at that point; the remaining items are saved unmodified |
| Throws while transforming an item | Rejected at that point; the remaining items are saved unmodified |
| Takes longer than about 1 second on one item (for example, an endless loop) | Rejected at that point; the remaining items are saved unmodified |
| Uses date operations (`new Date`, `Date.now`, `1970`) | Rejected-use the `until` input to filter by date instead |

If your output does not look transformed, check the run log for a warning that starts with `Your "customMapFunction" input was rejected:`-it explains exactly what was wrong.

If you do not need to transform the output, simply leave this field empty.

### 🔌 Send results straight into Notion, Todoist and more (MCP connectors)

Skip the manual exports — the scraper can deliver its results directly into the tools you already work in, through [Apify MCP Connectors](https://apify.com/store/collections/mcp-connectors?fpr=yhdrb):

1. Authorize a connector (Notion, Todoist, or any service whose MCP server offers non-destructive write tools) once in [Console → Settings → API & Integrations → MCP connectors](https://console.apify.com/settings/integrations).
2. Pick it from the **Send results to Notion, Todoist, …** dropdown.
3. Fill in where and how to write:
   - **Destination target** — paste the URL or ID (Notion example: `https://www.notion.so/My-Posts-24f8a1b2c3d44e5f8a9b0c1d2e3f4a5b`); share it with your connector first via Notion's **••• → Connections** menu. (Some services need no target.)
   - **Write mode** — `perPost` writes one record per scraped item; `summary` writes a single roll-up for the run.
   - **Max records to deliver** *(optional)* — cap on how many records `perPost` delivers.

**Notion, structured like a spreadsheet:** point the target at a Notion **page** and the Actor auto-creates a database with one correctly-typed column per field (URL, number, date, text). An **existing database** fills the columns it already has (matched by name); an **empty database** receives only the title, with the rest of each record in the row body. Nested fields are flattened too (e.g. `location` becomes `location.name`, `location.city`, `location.lat`, …), and the full record is kept in each row's page body.

Your credentials stay yours: the Actor only talks to your services through your own authorized connector and only uses non-destructive write tools — it cannot delete or overwrite anything you already have. Delivery is best-effort and runs after scraping: if it fails or the connector is misconfigured, the run still finishes successfully with all results intact and a warning in the log. If the run is about to time out, delivery stops early and the log tells you how many records were delivered.

### 🔧 Troubleshooting

- **Getting Few Results?** Check "Maximum number of items on output" (`maxItems`) field, and "Maximum charged results" fields. These two fields enable you to handle the total number of results. Leaving both empty will result infinite results.
- **Are Some Outputs Missing?** Ensure that you review all fields, not just the overview. You can navigate to the "Storage" tab and select either "Download the results" or "Open in a New Tab."
- **Getting No Results?** Confirm that your parameters are not overly restrictive.
- **Not Receiving New Items After a Large Batch?** Examine the log for messages like "Logging is too fast, some lines were skipped." If you encounter this issue, consider scraping smaller amounts of data to avoid it.

### 📞 Contact and Feature Requests

If you need any sort of support, please send an email to <apidojo10@gmail.com>. You name it, we get it.

### 🈴 Other Actors you might want to check

- [Twitter Scraper Lite](https://apify.com/apidojo/twitter-scraper-lite?fpr=yhdrb)
- [Instagram Scraper](https://apify.com/apidojo/instagram-scraper?fpr=yhdrb)
- [Instagram Comments Scraper](https://apify.com/apidojo/instagram-comments-scraper?fpr=yhdrb)
- [Tweet Scraper](https://apify.com/apidojo/tweet-scraper?fpr=yhdrb)
- [Twitter User Scraper](https://apify.com/apidojo/twitter-user-scraper?fpr=yhdrb)
- [TikTok User Scraper](https://apify.com/apidojo/tiktok-user-scraper?fpr=yhdrb)

# Actor input Schema

## `startUrls` (type: `array`):

Instagram location URLs. Paste the URLs, and get the results immediately. Location URLs are supported.

## `locationIds` (type: `array`):

Instagram Location IDs that you want to get from Instagram

## `maxItems` (type: `integer`):

Maximum number of items that you want as output.

## `until` (type: `string`):

Only include posts created on or after this date.

## `customMapFunction` (type: `string`):

JavaScript function to transform each output post. Use to add computed fields, modify values, or remove unnecessary data. NOT intended for filtering - filtering may result in automatic bans. Must be a single synchronous function, e.g. (object) => { return {...object} }. It runs in a sandbox with plain JavaScript only (no network, require or console) and about 1 second per item. Leave empty if you do not need to transform the output - an unusable function is ignored and the original items are saved instead.

## `outputConnector` (type: `string`):

Pick an MCP connector you authorized in Console → Settings → API & Integrations → MCP connectors (e.g. Notion, Todoist — any service whose MCP server offers non-destructive write tools works best-effort). The scraped results are written through your own connector — the Actor never sees your third-party credentials. Only non-destructive write tools are used; it can never delete or overwrite your existing data.

## `deliverTarget` (type: `string`):

Where to write into the connector — paste the URL or ID. Notion example: https://www.notion.so/My-Posts-24f8a1b2c3d44e5f8a9b0c1d2e3f4a5b. Leave empty for services that need no target (e.g. Todoist Inbox, Slack). For Notion, share the page or database with your connector first (Notion's ••• → Connections menu), and point at a PAGE for structured columns (the Actor builds the database for you) — an empty database receives only the title (the rest of each record goes to the row's body).

## `deliverMode` (type: `string`):

perPost writes one record per scraped item; summary writes a single roll-up for the run.

## `deliverMaxItems` (type: `integer`):

Cap on how many records perPost mode writes to the connector; ignored in summary mode. Leave empty to deliver everything scraped.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.instagram.com/explore/locations/213131048/berlin-germany/"
  ],
  "locationIds": [
    "213385402"
  ],
  "maxItems": 1000,
  "until": "2025-01-01",
  "customMapFunction": "(object) => { return {...object} }",
  "deliverMode": "perPost"
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        "https://www.instagram.com/explore/locations/213131048/berlin-germany/"
    ],
    "locationIds": [
        "213385402"
    ],
    "maxItems": 1000,
    "until": "2025-01-01",
    "customMapFunction": (object) => { return {...object} }
};

// Run the Actor and wait for it to finish
const run = await client.actor("apidojo/instagram-location-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": ["https://www.instagram.com/explore/locations/213131048/berlin-germany/"],
    "locationIds": ["213385402"],
    "maxItems": 1000,
    "until": "2025-01-01",
    "customMapFunction": "(object) => { return {...object} }",
}

# Run the Actor and wait for it to finish
run = client.actor("apidojo/instagram-location-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://www.instagram.com/explore/locations/213131048/berlin-germany/"
  ],
  "locationIds": [
    "213385402"
  ],
  "maxItems": 1000,
  "until": "2025-01-01",
  "customMapFunction": "(object) => { return {...object} }"
}' |
apify call apidojo/instagram-location-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,apidojo/instagram-location-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/KGXfArqc140ssBfl0/builds/15w9y5Vuo4NKMUsF7/openapi.json
