Save Profile Images with Apify

Use two Apify Actors to export profile posts and download their images.

Introduction

30 Second Summary

Saving a post on Instagram keeps it inside the app. Getting the actual image files can leave you opening posts one at a time.

In this project, you will use Apify to collect posts from a profile you control. You will chain two hosted Actors so one creates a dataset of post records while the other downloads the images.

What You'll Build

You will open a local folder filled with images from a profile you control, with matching post records saved as JSON.

By the end of this project, you'll have:

  • A capped profile scrape that collects a controlled number of posts and shows each one as a dataset record.
  • A clear way to inspect post data and identify the image URL stored inside each record.
  • A downloaded image folder on your machine, plus an exported JSON dataset you can keep.
  • An optional Secret Mission to push your skills further.

What do I need before starting?

You need an Apify account and a browser. Use a profile you own or run so you have the right to keep its content.

Before We Start

Instagram's save button keeps a post inside the app. It does not create the local archive this project needs.

Apify runs hosted scrapers called Actors. In this step, you will prepare your account permissions plus a local destination for the files.

In this step, get ready to:
  • Confirm that you have permission to archive the profile.
  • Create an Apify account with access to the Apify Console.
  • Choose a local location for the exported data plus downloaded images.
Choose content you can archive

This pipeline creates copies of profile data plus image files. Use it only with a profile you own or have permission to archive.

  • Choose one Instagram profile that you own or have permission to archive.
Create your Apify account

Account setup uses your sign-in details. Your password stays out of every screenshot plus checkpoint in this project.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type the name of your preferred web browser into the search bar.
  • Press Enter to open the browser.
  • Visit the Apify Console account guide in your browser.
  • Select the sign-up page link under Create an account.
  • Choose the account creation method that fits you below.

Email and password

  • Enter your email address.
  • Create a password that passes the strength indicator.
  • Click Sign up.
  • Open the verification email from Apify.
  • Select the verification link to continue to Apify Console.

Google

  • Click Continue with Google.
  • Complete the sign-in flow on Google's authentication page.
  • Authorize Apify to access your account.

GitHub

  • Click Continue with GitHub.
  • Complete the sign-in flow on GitHub's authentication page.
  • Authorize Apify to access your account.
  • Verify your email address if Apify asks you to complete that step.
  • Confirm that Apify Console opens after authentication.
  • Check that the Dashboard section is visible.

That account is ready. You now have a signed-in Console where each scraper run can store its results.

Verification email missing?

  • Check the spam folder for a message from Apify.
  • Return to the sign-in page through the account guide.
  • Click Resend verification email on the verification page.

Still blocked? Help me finish verifying my Apify account.

Prepare a download location

The final export produces a JSON file plus a folder of images. Choosing the destination now gives those files a location you can return to later.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Finder (macOS) or File Explorer (Windows) into the search bar.
  • Press Enter to open the file browser.

macOS

  • Select an existing folder in Finder that you can use for this project.
  • Record your chosen location as your chosen download folder.

Windows

  • Select an existing folder in File Explorer that you can use for this project.
  • Record your chosen location as your chosen download folder.

Before the final check, do you expect both your Console access plus your local destination to be ready?

  • Switch back to the Apify Console browser tab from earlier.
  • Confirm that the Dashboard section remains visible.
  • Return to your chosen download folder in your file browser.
  • Confirm that the selected folder location opens on your computer.

Everything is in place. Your scraper results now have a signed-in platform to run from plus a local destination to land in.

✔️ My setup matches

Your Apify account is ready. Your local download location is also available.

ⓧ I'd like to double check

Created and signed in to the Apify Console.

A location on the local computer is available for the exported JSON file and downloaded image folder.

Your account permissions plus download destination are ready. Next, you will run a profile scraper Actor against one permitted post.

Test the Profile Scraper

Your Apify account is ready. A whole-profile scrape has too many moving parts for a first check.

One authorized Instagram post gives the Actor a known target.

You will run that small test. You will open its single dataset record as proof.

In this step, get ready to:
  • Open the Instagram Scraper Actor in Apify Console.
  • Configure one authorized post URL for a single-result run.
  • Open the default dataset to confirm one post record.
Open the Instagram Scraper Actor

Actors are hosted programs that accept an input before writing their results to storage. Instagram Scraper handles the post URL for this test.

  • Open the official Instagram Scraper page in your browser.
  • Click Try for free to load the Actor in Apify Console.
  • Confirm the page title shows Instagram Scraper.

Why start with one post?

A one-record test makes it easier to isolate a scraper problem from a profile-scale issue. Once this works, the next run can widen the target.

Run one authorized post

The test input needs to identify one post that you own or have permission to archive. A direct post URL gives the Actor one precise target.

This run consumes some of your Apify usage. Your one-result cap keeps the test controlled.

  • Open one authorized Instagram post in a separate browser tab.
  • Copy the post URL from your browser address bar.
  • Record the copied URL here: your authorized post URL.
  • Return to the Instagram Scraper Actor in Apify Console.
  • Select Posts under Content to scrape.
  • Paste your authorized post URL into Instagram URLs based on content type.
  • Enter 1 under Results limit per URL.
  • Click Save & Start.

The run page streams log entries while the Actor processes your URL.

Inspect one dataset record

A dataset stores the structured records produced by a run. Each item represents one scraped result.

Before you inspect the result, how many records do you expect from one direct post URL?

  • Wait for the Actor run to finish.
  • Select Storage on the completed run page.
  • Select Dataset to open the default dataset view.

You should see one item in the dataset table. Its fields describe the authorized post you supplied.

Run did not produce a record?

  • Confirm the URL opens a single public post in a signed-out browser window.
  • Confirm Posts remains selected under Content to scrape.
  • Run the test again after correcting the input.

Still stuck? Help me diagnose why my Instagram Scraper run did not create one dataset record.

That first record is a strong checkpoint. Your Actor can accept an authorized post URL and write its result to a dataset.

Your test run now proves the scraper can collect a post record. Next, you will point the same Actor at a whole profile with a controlled post limit.

Scrape Your Profile Posts

Your one-record test proved that an Apify Actor can turn an authorized Instagram post into a dataset record.

A whole profile can contain far more posts than you need. A maximum-post cap keeps this first profile run bounded while the Actor fills its default dataset.

In this step, get ready to:
  • Configure the scraper with one authorized profile URL.
  • Limit the maximum number of posts collected from that profile.
  • Complete a profile scrape that produces a capped default dataset.
Set the profile URL and post cap

The target URL determines which profile the Actor reads. Results limit per URL places a ceiling on how many post records that target can produce.

  • Return to the Instagram Scraper Actor from your test run's dataset view.
  • Confirm that Content to scrape remains set to posts.
  • Replace the single-post target in Instagram URLs based on content type with your authorized Instagram profile URL.
  • Enter your chosen maximum-post cap in Results limit per URL.

Why cap the run?

The cap sets the highest number of records the Actor can collect from this URL. Your dataset can finish below that limit when the profile contains fewer available posts.

Run the capped profile scrape

The run log is a live trace of what the Actor collects. Each new entry gives you evidence that the profile target is producing records.

Starting this run uses Apify usage. Your post cap keeps the amount bounded.

  • Click Save & start.
  • Watch the run log while the Actor processes your profile.
  • Wait for the run to reach its completed state.

You have moved from a one-post proof to a bounded profile scrape. The completed log now shows the Actor collecting post records from your authorized profile.

Run not collecting posts?

  • Confirm that the authorized profile is public.
  • Confirm that your authorized Instagram profile URL points to the profile page.
  • Check that Content to scrape is still set to posts.

Still stuck? Help me diagnose why my Instagram Scraper run is not collecting posts from an authorized public profile.

Confirm the dataset record count

Each collected post becomes one item in the completed run's default dataset. The item count proves that the scraper stored the records shown in the log.

Before you check, do you expect the dataset to reach your cap or stop below it because the profile has fewer available posts?

  • Select Storage on the completed run page.
  • Select Dataset in the storage area.
  • Record the default dataset item count as your profile dataset record count.
  • Compare your profile dataset record count with your chosen maximum-post cap.

You should see the collected post records listed in the default dataset.

Your count of your profile dataset record count should be no greater than your chosen maximum-post cap. A lower count means the profile had fewer available posts than your cap.

That is the full-profile scrape working. Your capped dataset is ready for inspection.

Dataset is empty?

  • Return to the completed run log.
  • Check whether the Actor could access the authorized profile.
  • Run the Actor again after correcting the profile URL or content type.

Need another set of eyes? Help me work out why my completed profile scrape created an empty default dataset.

Your capped profile dataset is ready. Next, you will inspect one record and locate the field that points to its image.

Inspect the Profile Dataset

Your completed profile scrape in Apify Console has turned one authorized profile into a dataset of post records. The next Actor needs a precise image source from those records.

In this step, you will open that dataset. You will inspect one record to identify the field that holds its image URL.

In this step, get ready to:
  • Open the default dataset from the completed profile run.
  • Inspect one post record in JSON view.
  • Identify displayUrl as the image source for the downloader Actor.
Open the profile dataset

Each dataset item contains the information collected for one post. Opening the dataset lets you inspect those items beyond the run log.

  • Switch back to the completed profile scraper run from earlier.
  • Select the Storage tab on the run detail page.
  • Select Dataset to open the default dataset.

You will see up to your chosen maximum-post cap of rows from the authorized profile. Each row represents one post record.

How Does a Dataset Work?

An Apify dataset stores each scraped result as a separate item. This layout gives every post a consistent set of fields.

The next Actor can read the same image field across those items. That consistency turns the dataset into the handoff between the two Actors.

Cannot Find the Profile Records?

  • Return to the completed whole-profile run from earlier.
  • Select the dataset attached to that run under the Storage tab.
  • Check the selected run if you see only the single record from your earlier test.

Still stuck? Help me find the default dataset from my completed Apify Actor run.

Inspect a post record

A JSON view exposes the exact field names inside each post record. This view keeps each field beside its stored value.

  • Select the JSON view for the profile dataset.
  • Inspect the first post object in the dataset.

Before you make the final check, where do you expect the image address to sit inside the record? Your prediction is ready to test.

  • Locate displayUrl inside the first post object.
  • Read the long web address stored beside displayUrl.

You will see displayUrl paired with the post's image address. You found the handoff point that the downloader Actor can use.

Cannot See the Image Field?

  • Switch to the JSON view if the table hides some fields.
  • Return to the completed whole-profile run if the dataset contains only your earlier test record.
  • Check another post object if the first record is difficult to read.

Need another pair of eyes? Help me locate displayUrl in my Apify dataset record.

Your profile dataset is open with its image source identified. Next, you will feed that dataset into the downloader Actor.

Download Images with an Actor

Your profile dataset now shows where each post points to its image. Those records still contain links, so the images are not yet stored as files.

Now you'll pass that dataset to Dataset Image Downloader & Uploader in the Apify Console. This Actor follows the identified field in each record and writes the downloaded files into the run's key-value store.

In this step, get ready to:
  • Capture the profile dataset ID and the identified image URL field.
  • Configure the downloader Actor to read the profile dataset.
  • Run the downloader and verify the image files in key-value storage.
Copy the profile dataset ID

A dataset ID gives another Actor the exact address of your stored records. The downloader also needs the image URL field you identified earlier.

  • Locate the dataset ID above the records in the profile dataset from earlier.
  • Copy the dataset ID to your clipboard.
  • Record the copied value here: your profile dataset ID.
  • Record the field you identified earlier here: your image URL field.

You now have the two coordinates the downloader needs. One points to the records, while the other points to the image URL inside each record.

Configure the downloader Actor

Dataset Image Downloader & Uploader reads existing Apify storage. Its input connects your profile dataset to the field containing the image URLs.

You'll see the Actor input form in the Apify Console.

  • Paste your profile dataset ID into the Dataset Id field.
  • Paste your image URL field into the Path to image URLs field.

The two populated fields now identify the source records and the location of each image URL.

  • Select key-value-store from the Upload to dropdown.
  • Keep the remaining settings at their default values.

How does this connection work?

  • The dataset ID tells the downloader which collection of post records to read.
  • The image URL path tells the downloader where to find the source link inside each record.
  • The upload destination tells the Actor to save the fetched image files in key-value storage.
Run the downloader and inspect storage

The configured Actor now has everything it needs to fetch the files. The completed run keeps its downloaded output separate from your original profile dataset.

Before you start the run, where do you expect the image files to appear: the profile dataset or the downloader run's key-value store?

Starting the Actor consumes some of your Apify usage. Your earlier post cap keeps this run tied to that bounded dataset.

  • Click Start to run the downloader Actor.

The run may take a little while because the Actor visits each image URL separately.

  • Wait for the downloader run to finish.

The completed run confirms that the Actor processed the image URLs from your profile dataset.

  • Select Storage on the completed downloader run.
  • Select Key-value store to inspect the downloaded output.

You'll see image files stored with the completed run. Your original profile dataset remains available in the Apify Console.

Key-value store looks empty?

  • Check that the dataset ID matches the profile dataset you inspected earlier.
  • Check that the image URL path matches the field name exactly.
  • Confirm that the upload destination is set to key-value storage.

Still stuck? Help me troubleshoot an empty key-value store after running an Apify image downloader Actor.

That is the key handoff complete. Your dataset records have now produced stored image files.

Your image files now live in the downloader run's key-value storage. Next, you'll export the profile dataset as JSON. You'll also bring both outputs onto your computer.

Export Records and Save Your Files

The downloader run has turned the profile dataset into image files inside the Apify Console's key-value store. Those files still live in cloud storage.

Now you will export the profile dataset as JSON. You will also save the images in a local folder for a portable copy of the profile.

In this step, get ready to:
  • Save the profile dataset as a JSON file.
  • Download the image records from the downloader run.
  • Verify the extracted image folder against the dataset.
Export the profile dataset as JSON

JSON stores each post record as structured data. The visible record count gives you a baseline for checking the files after download.

  • Switch back to the completed profile scraper run from earlier.
  • Select Dataset in the run details.
  • Confirm that the visible rows belong to the authorized profile from your capped run.
  • Record the number of profile records shown: your dataset record count.
  • Click Export.
  • Choose JSON as the export format.
  • Click Download to save the dataset.
  • Move the downloaded .json file to your available local download location.

That is your first local deliverable: the profile's structured records now exist outside Apify as a JSON file.

Dataset File Missing?

  • Check your browser's download history for a file ending in .json.
  • Return to the profile dataset if the file is missing.
  • Repeat the export with JSON selected.

Need another pair of eyes? Help me find the JSON file I exported from my Apify dataset.

Download the image archive

The downloader's key-value store holds each image as a separate record. Downloading all records packages the store into a ZIP archive so the files can leave the console together.

  • Switch back to the completed downloader run from earlier.
  • Select Key-value store in the run details.
  • Click the store ID to open its detail page.
  • Scroll to the records area at the bottom of the page.
  • Choose the option to download all records at once.
  • Move the downloaded archive to the same local location as your dataset export.

The cloud files are now in your hands: you should see a downloaded file ending in .zip.

Why Download All Records?

A key-value store can contain many separate files. Downloading all records collects them into one archive without changing the copies stored in Apify Console.

Archive Did Not Download?

  • Check your browser's download history for a file ending in .zip.
  • Confirm that the open key-value store belongs to the completed downloader run.
  • Return to the record list if the wrong store is open.

Still stuck? Help me download every image record from my Apify key-value store.

Unpack and verify the image folder

A ZIP archive bundles many image files into one download. Extracting it creates the local image folder you can inspect.

macOS

  • Press Cmd+Space to open Spotlight.
  • Type Finder to open Finder.
  • Navigate to the local download location you used above.
  • Double-click the downloaded .zip file to extract it.

Windows

  • Press the Windows logo key + E to open File Explorer.
  • Navigate to the local download location you used above.
  • Right-click the downloaded .zip file.
  • Select Extract All....
  • Follow the extraction instructions to create the local folder.

Before you open the extracted folder, how closely do you expect its image count to match the dataset record count?

  • Open the extracted folder in Finder or File Explorer.
  • Count only the image files inside the folder.
  • Compare that count with your dataset record count.
  • Open one image file to inspect its contents.

You should see the same number of image files as the profile dataset records. The image you open should show content from the authorized profile.

File Count Does Not Match?

  • Exclude the archive itself from your image count.
  • Exclude any non-image storage records from your image count.
  • Repeat the download from the completed downloader run if image files are missing.

Need help comparing the outputs? Help me work out why my Apify dataset record count and local image count differ.

That is the full handoff complete: your JSON export and opened image folder now live on your computer. The dataset and key-value store remain available in Apify Console for review or cleanup.

Secret mission

Audit Your Download for Completeness

Prove that the image files produced by your downloader reached your computer. Reconcile the dataset, downloader storage, and local folder before spot-checking three images.

Clean Up Your Resources

Clean Up Your Resources

Your capped Actor runs fit within Apify's free usage for this project. Hosted datasets plus key-value storage can still count against that allowance until you delete them.

Decide whether to keep your resources available, pause new runs to come back later, or delete them entirely.

Resources you used:

  • Apify profile scraper test run with its one-record default dataset.
  • Apify whole-profile scraper run with its capped profile dataset.
  • Apify downloader Actor run with its image-file key-value storage.
  • Exported profile dataset JSON file on your local computer.
  • Verified local folder containing the downloaded image files.

Keep everything running

No action is needed. Choose this if you want to review the pipeline or reuse the downloaded results.

  • Leave the completed profile scraper runs in the Apify Console.
  • Leave the completed downloader Actor run in the Apify Console.
  • Keep the profile datasets available for inspection.
  • Keep the downloader key-value storage available for another download.
  • Retain the exported JSON file on your local computer.
  • Retain the verified image folder on your local computer.

Pause - I'll come back to this later

Every Actor run is already complete, so there is no active process to stop. Pausing means avoiding new runs while your existing results stay available.

  • Avoid starting another profile scraper run.
  • Avoid starting another downloader Actor run.
  • Leave the hosted datasets unchanged.
  • Leave the downloader key-value storage unchanged.
  • Keep the local JSON export for your return.
  • Keep the local image folder for your return.

Delete - I don't want to use this again

Remove the project resources when you want a complete reset. Deletion is permanent, so each resource stays separate to give you control over what disappears.

Hosted resources:

  • Delete the one-record default dataset through the storage details page for the completed profile scraper test run.
  • Delete the completed profile scraper test run through its run details page.
  • Delete the capped profile dataset through the storage details page for the completed whole-profile scraper run.
  • Delete the completed whole-profile scraper run through its run details page.
  • Delete the downloader key-value storage through its storage details page.
  • Delete the completed downloader Actor run through its run details page.
  • Confirm that the deleted datasets plus key-value storage no longer appear in your Apify storage list.
  • Confirm that the deleted Actor runs no longer appear in your Apify run list.

Local copies:

  • Return to the local download location from earlier in Finder on macOS or File Explorer on Windows.
  • Move the exported JSON file to Trash on macOS or the Recycle Bin on Windows.
  • Move the downloaded image folder to Trash on macOS or the Recycle Bin on Windows.
  • Permanently delete only those project items from Trash or the Recycle Bin.
  • Confirm that the exported JSON file is absent from the local download location.
  • Confirm that the downloaded image folder is absent from the local download location.

Nice Work!

Nice Work!

You made it! Your repeatable Apify pipeline now turns an authorized profile into a local archive containing structured post records plus matching image files.

You've learned how to:

  • Run a capped profile scraper Actor against an authorized profile. You can watch its dataset fill with post records.
  • Inspect a record to find its image URL field. You can connect the dataset to a downloader Actor. Its files appear in key-value storage.
  • Export the profile dataset as JSON. You can download the matching images into a local folder. Opening that folder confirms the archive reached your computer.
  • Secret Mission: Complete an optional challenge that pushes your profile archiving skills further.

Ready to quiz yourself?