How to download Instagram photos by hashtag
Published
To download Instagram photos by hashtag, you need a tool that reads the hashtag's feed while signed in to an Instagram account, because Instagram's own app has no button that saves somebody else's photo to your device. For a handful of photos, opening each post and saving it by hand is fine. For a whole folder in one go, the free command line tool Instaloader downloads every post on a hashtag, videos included. And when you want to look at the posts first and only keep the good ones, you can pull the hashtag as a list of rows, filter it in a spreadsheet, and download just the images you picked. This guide walks through all three, and the permission question that comes before any of them.
It is written for people who need the pictures themselves: a brand gathering customer photos from a campaign tag, an event team collecting the night's shots, a researcher building an image set, a designer making a mood board.
Before you download: whose photos are these?
A photo posted under a hashtag still belongs to the person who took it. Downloading it for your own review, research or reference is one thing. Putting it on your website, in an ad or in a printed piece is reuse, and reuse needs the creator's permission and a credit. Using your hashtag is not the same as granting that.
So whichever route you take below, keep two facts with every file: the link to the original post and the username that posted it. Without them you have a picture you cannot credit and cannot ask about. Our guide to collecting user generated content on Instagram covers the permission request step by step, and is it legal to scrape Instagram covers what Instagram's terms say about automated collection.
The three ways compared
| By hand | Instaloader | List first, then download | |
|---|---|---|---|
| Best for | Up to a dozen photos | Everything on a tag, as files | Choosing before you download |
| What you get | The photos you save | Photos, videos and caption files in a folder | A spreadsheet of posts, then the cover images you pick |
| Videos | Screen recording only | Yes, unless you turn them off | No, a still image per post |
| Every slide of a carousel | Yes, one at a time | Yes | No, one image per post |
| Needs an Instagram login | Yes | Yes, for hashtags | Yes, a session cookie |
| Runs on | Your phone or browser | Your own computer, in Python | A hosted service, then a short script |
| Cost | Free | Free | Pay per post delivered |
The rest of this page goes through each column in order.
Way 1: save a few photos by hand
When you only want a few pictures, the manual route is quick and needs nothing installed.
- Sign in to Instagram in a browser or the app. A signed-out visitor sees very little on a hashtag page, which searching Instagram hashtags without an account explains.
- Search the hashtag and open its page.
- Open each post you want.
- Save the image. On a phone that is usually a screenshot, cropped to the photo. In a desktop browser you can screenshot the post or use your browser's developer tools to find the image file.
- Write down the post link and the username beside each file, straight away.
The bookmark icon in the app saves a post to your collections. That keeps it inside Instagram for later, which is handy, but it does not put a file on your device.
This stops working at around a dozen photos, or as soon as you need every post from a date range rather than whatever the feed shows you first. Seeing all posts under a hashtag explains why the hashtag page is a poor place to look for completeness.
Way 2: download a whole hashtag with Instaloader
Instaloader is a free, open source tool written in Python that downloads pictures and videos from Instagram. If what you want is the files themselves, in a folder, it is the most direct route. Everything here comes from its own documentation, as of October 2026.
Its usage page lists "#hashtag" as a download target, with this note:
Posts with a certain hashtag (the quotes are usually necessary). Requires login.
So you need an Instagram account to sign in with. Use one you are prepared to see rate limited, because a heavy download is exactly what Instagram limits.
Steps
- Install Python, then install the tool with
pip install instaloader. Download the hashtag, signing in with your account:
instaloader --login=your_username --count=50 "#coffee"--countcaps the number of posts. Its documentation describes it as "Do not attempt to download more than COUNT posts", and says it applies to hashtags.- Open the new
#coffeefolder. Instaloader creates one directory per target and names each file after the post's timestamp.
Options worth knowing
- Photos only.
--no-videosskips video files, and--no-video-thumbnailsskips their preview images too. - Only the first slide of each carousel.
--slide 1downloads just the first image of a multi-image post. - Less clutter.
--no-metadata-jsonstops the JSON file it writes beside each post, and--no-captionsstops the caption text files. - Only the popular posts.
--post-filter="likes>100"keeps posts above a like count. The documentation's own example filters a hashtag by the other tags in the caption:--post-filter="'cute' in caption_hashtags" "#kitten". - Topping up later.
--fast-updatestops at the first picture it has already downloaded, so a second run only fetches what is new.
Where it gets hard
Instaloader is a client you run yourself, so you look after it. Its troubleshooting page describes login problems and rate limiting, especially when it runs on a cloud server, a VPN or a proxy rather than a home connection. Our Instaloader alternatives article goes through those trade-offs in detail. For an occasional download from your own laptop, none of it is likely to bother you.
Way 3: list the posts first, then download the ones you want
Instaloader downloads everything it reaches, and you sort through the folder afterwards. Often the order is the wrong way round: you want to see the posts as a list, decide which ones are worth keeping, and only then download those. That matters when a campaign tag has a thousand posts and you need the forty best, or when a reviewer has to approve each photo before anyone asks the creator for permission.
The Instagram Hashtag Scraper is one way to do the listing part. It is an actor that runs on Apify. You give it one hashtag, a session cookie for an Instagram account you control, a maximum number of posts and an optional date window, and it writes the posts to a dataset, newest first, one row per post. The getting started page shows where the cookie comes from.
Step 1: pull the hashtag as rows
- Open the actor from the overview page and start a new run.
- Enter the hashtag, with or without the
#. - Set the result limit. It is exact: you never receive or pay for more posts than this number.
- Optionally set onlyPostsNewerThan to the start of your campaign or event, for example
2026-09-01or14 days. The run stops when the feed reaches that date. - Paste your session cookie and run it.
It charges $0.0005 per post delivered to your dataset, so 1,000 posts cost $0.50.
Step 2: choose in a spreadsheet
Export the dataset as CSV or Excel. These are the columns that matter for picking photos:
| Column | What it is for |
|---|---|
url | Opening the post to look at it properly |
ownerUsername | Who to credit, and who to ask for permission |
takenAt | When it was posted, for sorting and for checking a date window |
likeCount | A rough signal of which posts people responded to |
mediaType | Whether the post is an image, a video or a carousel |
displayUrl | A link to the post's image, for downloading |
Add a keep column, mark the rows you want, and filter to them. If several people are reviewing, share the sheet and let them mark it. Exporting Instagram posts to Excel has more on working with the sheet.
Step 3: download the images you marked
Save the filtered rows as picked.csv. This short Python script, using only the standard library, downloads each row's image and names the file after the post and its author, so the credit travels with the file:
import csv
import pathlib
import urllib.request
out = pathlib.Path("photos")
out.mkdir(exist_ok=True)
with open("picked.csv", newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
link = row.get("displayUrl")
if not link:
continue
name = f"{row['shortcode']}_{row.get('ownerUsername') or 'unknown'}.jpg"
urllib.request.urlretrieve(link, out / name)
print("saved", name)
Run it soon after the scrape. Instagram serves these image links from its own servers with signed addresses that stop working after a while. A sheet of links that worked today may be a sheet of broken links next week. The url column keeps working, so you can always go back to the post itself.
What this route does not give you
Be clear on the limits before you choose it:
- One image per post.
displayUrlis a single still image: the largest version the feed offers. For a carousel that is one picture, not every slide. For a video it is a still frame, not the video. - Sometimes no image link at all. When the feed offers no still image for a post, the field is empty rather than broken. The script above skips those rows, and the
urlstill opens the post. - No video files. If you need the videos themselves, Instaloader is the better tool.
Downloading videos and reels by hashtag
People who search for photos often want the reels too. Of the three routes, only Instaloader downloads the video files from a hashtag. It does that by default, so leave out --no-videos.
The list-first route still helps here. The mediaType and containsVideo columns tell you which posts are videos, so you can build a shortlist of the reels you want, then open each url to watch it before deciding. What it hands you for a video is a still image and a link, never the video file.
When the manual way is enough
Most people who want a few photos from a hashtag do not need a tool at all. Stay with saving by hand when:
- you want fewer than a dozen photos;
- you are picking by eye and do not need every post from a date range;
- this is a one-off, not a weekly job;
- you have no permission plan yet, so you are only collecting references for yourself.
Reach for Instaloader when you want the files, videos included, and you are comfortable running a command on your own computer. Reach for the list-first route when choosing matters more than downloading everything: a campaign with hundreds of entries, a team that reviews before anyone reuses, or a date window you need to get exactly right. If the hashtag is a contest, running an Instagram hashtag contest covers collecting the entries and picking a winner from the same sheet.
A quick checklist
- Decide what you will do with the photos, and whether that needs the creator's permission.
- Pick the route: by hand for a few, Instaloader for a whole folder, list first when you need to choose.
- Sign in with an account you are willing to have rate limited.
- Keep the post link and the username with every file.
- Download promptly, before image links expire.
- Ask permission and credit the creator before anything is reposted.