# Instagram Posts Scraper With Tagged Places & Coordinates (`simpleapi/instagram-posts-scraper`) Actor

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.

- **URL**: https://apify.com/simpleapi/instagram-posts-scraper.md
- **Developed by:** [SimpleAPI](https://apify.com/simpleapi) (community)
- **Categories:** Automation, Lead generation, Social media
- **Stats:** 12 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### 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`, and `externalId` parsed out of Instagram's raw `location` object into a clean `taggedPlace` field, plus a `hasLocation` flag on every post.
- 🔎 **Only-geotagged mode** — `onlyGeotagged` skips posts with no tagged place and keeps scanning further pages until it collects `postsPerProfile` geotagged posts (or the profile/date range runs out).
- 🏆 **Per-profile top-places roll-up** — `topPlacesPerProfile` adds one `locationSummary` row per profile, ranking that creator's most-frequently-tagged places by scanned-post count.
- 📅 **Absolute or relative date filtering** — `dateFilterType` + `filterDate` keep only posts newer than a calendar date or a relative window like `30d`.
- 🌐 **Proxy-backed requests** — every request runs through `proxyConfiguration` via `Actor.create_proxy_configuration`, defaulting to Apify's `RESIDENTIAL` group 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"] }` |

```json
{
  "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.

```json
[
  {
    "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.

1. **Date scope** — `dateFilterType` chooses 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.
2. **Quality threshold** — `onlyGeotagged` is the actor's precision filter: instead of returning whatever the feed hands back, it keeps scanning further pages specifically until it has `postsPerProfile` posts that actually carry a tagged place.
3. **Volume control** — `postsPerProfile` caps how many posts count toward the target per profile, and `topPlacesPerProfile` caps how many places appear in the roll-up. When `onlyGeotagged` is 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.

```json
{ "profileUrls": ["https://www.instagram.com/natgeo/"], "dateFilterType": "relative", "filterDate": "30d", "postsPerProfile": 40 }
```

```json
{ "profileUrls": ["https://www.instagram.com/natgeo/"], "onlyGeotagged": true, "postsPerProfile": 20, "topPlacesPerProfile": 10 }
```

```json
{ "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

```python
from apify_client import ApifyClient

client = 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.

# Actor input Schema

## `profileUrls` (type: `array`):

List one or more Instagram profile URLs (e.g. https://www.instagram.com/username), bare usernames, or post shortcodes — the type is auto-detected. Example: \["https://www.instagram.com/natgeo/"] scans that profile's posts for tagged-place data.

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

Legacy alias of profileUrls, kept so input JSON built for the base Instagram Posts Scraper keeps working unchanged. Use profileUrls above for new runs — if both are set, profileUrls wins.

## `postsPerProfile` (type: `integer`):

How many of each profile's most recent posts to scan for tagged-place data (1-1000). Example: postsPerProfile=50 scans the last 50 posts of each profile in profileUrls. Default is 10.

## `maxPosts` (type: `integer`):

Legacy alias of postsPerProfile, kept so input JSON built for the base Instagram Posts Scraper keeps working unchanged. If both are set, postsPerProfile wins.

## `onlyGeotagged` (type: `boolean`):

ON: skip posts with no tagged place and keep scanning further pages until postsPerProfile geotagged posts are found (or the profile/date range runs out). OFF (default): return every scanned post, geotagged or not — each one still carries a hasLocation flag and a taggedPlace object (null when the post has no location).

## `topPlacesPerProfile` (type: `integer`):

How many of a profile's most-frequently-tagged places to list in that profile's roll-up row, ranked by how many scanned posts were tagged there. Example: topPlacesPerProfile=5 lists the 5 places this creator geotags most often. Set to 0 to skip the roll-up row entirely.

## `dateFilterType` (type: `string`):

Choose your date filter mode: an absolute calendar date, or a relative time range.

## `filterDate` (type: `string`):

Absolute mode: pick a calendar date with the datepicker (YYYY-MM-DD) — only posts newer than it are returned. Relative mode: type a relative value instead, like 7d (7 days), 2w (2 weeks), 3m (3 months), or 1y (1 year). Leave empty for no date filter. Example: dateFilterType=relative + filterDate=30d returns posts from the last 30 days.

## `includeEngagement` (type: `boolean`):

Whether to keep engagement fields (like/comment/view counts and related flags) on each post row. Default is off.

## `includeVideoMetadata` (type: `boolean`):

Whether to keep detailed video fields (duration, quality variants, codec info) on each post row. Default is off.

## `proxyConfiguration` (type: `object`):

Proxy used for every Instagram request this run makes. Residential proxy groups are strongly recommended for reliability; defaults to Apify's RESIDENTIAL group when left unset.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.instagram.com/natgeo/"
  ],
  "postsPerProfile": 10,
  "onlyGeotagged": false,
  "topPlacesPerProfile": 5,
  "dateFilterType": "relative",
  "filterDate": "",
  "includeEngagement": false,
  "includeVideoMetadata": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped items in the Actor's default dataset.

## `output` (type: `string`):

The same post and locationSummary rows as the dataset, saved as one JSON array record under the key OUTPUT in the key-value store.

# 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 = {
    "profileUrls": [
        "https://www.instagram.com/natgeo/"
    ],
    "postsPerProfile": 10,
    "onlyGeotagged": false,
    "topPlacesPerProfile": 5,
    "includeEngagement": false,
    "includeVideoMetadata": false,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("simpleapi/instagram-posts-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 = {
    "profileUrls": ["https://www.instagram.com/natgeo/"],
    "postsPerProfile": 10,
    "onlyGeotagged": False,
    "topPlacesPerProfile": 5,
    "includeEngagement": False,
    "includeVideoMetadata": False,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("simpleapi/instagram-posts-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 '{
  "profileUrls": [
    "https://www.instagram.com/natgeo/"
  ],
  "postsPerProfile": 10,
  "onlyGeotagged": false,
  "topPlacesPerProfile": 5,
  "includeEngagement": false,
  "includeVideoMetadata": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call simpleapi/instagram-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,simpleapi/instagram-posts-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/cp2yoKeWUQcvItQ2c/builds/raF76g4qyWyJ0Ffqw/openapi.json
