<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: irtiza</title>
    <description>The latest articles on DEV Community by irtiza (@irtiza_b94a0eae44e7504e96).</description>
    <link>https://dev.to/irtiza_b94a0eae44e7504e96</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4135599%2F8e32065f-7ab6-47a1-b31d-3681b80c5f13.png</url>
      <title>DEV Community: irtiza</title>
      <link>https://dev.to/irtiza_b94a0eae44e7504e96</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/irtiza_b94a0eae44e7504e96"/>
    <language>en</language>
    <item>
      <title>I built a small Instagram OSINT checker for public profiles</title>
      <dc:creator>irtiza</dc:creator>
      <pubDate>Mon, 21 Sep 2026 10:56:36 +0000</pubDate>
      <link>https://dev.to/irtiza_b94a0eae44e7504e96/i-built-a-small-instagram-osint-checker-for-public-profiles-53ec</link>
      <guid>https://dev.to/irtiza_b94a0eae44e7504e96/i-built-a-small-instagram-osint-checker-for-public-profiles-53ec</guid>
      <description>&lt;p&gt;What can I learn from an Instagram profile without logging in, scraping pages manually, or turning a quick check into a whole research project?&lt;/p&gt;

&lt;p&gt;That was the question behind a small tool I built for OSINT research.&lt;/p&gt;

&lt;p&gt;The goal wasn't to build a giant intelligence platform. I wanted something much smaller: give the tool a public Instagram username, fetch the available profile data, and make it easier to inspect things like public stories during an investigation.&lt;/p&gt;

&lt;p&gt;For the API layer, I used HikerAPI&lt;br&gt;
, a REST API for Instagram with pricing starting at $0.001 per request and 100 free requests.&lt;/p&gt;

&lt;p&gt;The basic experiment&lt;/p&gt;

&lt;p&gt;I started with the smallest possible Python test.&lt;/p&gt;

&lt;p&gt;import requests&lt;/p&gt;

&lt;p&gt;headers = {"x-access-key": "YOUR_KEY"}&lt;/p&gt;

&lt;p&gt;user = requests.get(&lt;br&gt;
    "&lt;a href="https://api.hikerapi.com/v2/user/by/username?username=apple" rel="noopener noreferrer"&gt;https://api.hikerapi.com/v2/user/by/username?username=apple&lt;/a&gt;",&lt;br&gt;
    headers=headers&lt;br&gt;
).json()&lt;/p&gt;

&lt;p&gt;resp = requests.get(&lt;br&gt;
    "&lt;a href="https://api.hikerapi.com/v2/user/stories" rel="noopener noreferrer"&gt;https://api.hikerapi.com/v2/user/stories&lt;/a&gt;",&lt;br&gt;
    params={"user_id": user["pk"]},&lt;br&gt;
    headers=headers&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;print(resp.json())&lt;/p&gt;

&lt;p&gt;There are two requests here.&lt;/p&gt;

&lt;p&gt;First, I resolve the username to a user object and get its pk. Then I use that ID to request the user's stories.&lt;/p&gt;

&lt;p&gt;That distinction matters because the second endpoint expects the internal user ID rather than the username.&lt;/p&gt;

&lt;p&gt;Turning it into a tiny research tool&lt;/p&gt;

&lt;p&gt;Once the request worked, I wrapped the same idea in a small CLI.&lt;/p&gt;

&lt;p&gt;The basic flow is:&lt;/p&gt;

&lt;p&gt;username&lt;br&gt;
   ↓&lt;br&gt;
resolve public profile&lt;br&gt;
   ↓&lt;br&gt;
get user ID&lt;br&gt;
   ↓&lt;br&gt;
request available stories&lt;br&gt;
   ↓&lt;br&gt;
print structured response&lt;/p&gt;

&lt;p&gt;I kept the output deliberately boring. For OSINT work, I generally prefer raw, inspectable data over a UI that tries to decide what is important for me.&lt;/p&gt;

&lt;p&gt;A minimal version looks like this:&lt;/p&gt;

&lt;p&gt;import argparse&lt;br&gt;
import json&lt;br&gt;
import requests&lt;/p&gt;

&lt;p&gt;API_URL = "&lt;a href="https://api.hikerapi.com/v2" rel="noopener noreferrer"&gt;https://api.hikerapi.com/v2&lt;/a&gt;"&lt;br&gt;
API_KEY = "YOUR_KEY"&lt;/p&gt;

&lt;p&gt;headers = {&lt;br&gt;
    "x-access-key": API_KEY&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;def get_user(username):&lt;br&gt;
    response = requests.get(&lt;br&gt;
        f"{API_URL}/user/by/username",&lt;br&gt;
        params={"username": username},&lt;br&gt;
        headers=headers,&lt;br&gt;
        timeout=20,&lt;br&gt;
    )&lt;br&gt;
    response.raise_for_status()&lt;br&gt;
    return response.json()&lt;/p&gt;

&lt;p&gt;def get_stories(user_id):&lt;br&gt;
    response = requests.get(&lt;br&gt;
        f"{API_URL}/user/stories",&lt;br&gt;
        params={"user_id": user_id},&lt;br&gt;
        headers=headers,&lt;br&gt;
        timeout=20,&lt;br&gt;
    )&lt;br&gt;
    response.raise_for_status()&lt;br&gt;
    return response.json()&lt;/p&gt;

&lt;p&gt;def main():&lt;br&gt;
    parser = argparse.ArgumentParser(&lt;br&gt;
        description="Inspect publicly available Instagram data."&lt;br&gt;
    )&lt;br&gt;
    parser.add_argument("username")&lt;br&gt;
    args = parser.parse_args()&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user = get_user(args.username)
stories = get_stories(user["pk"])

print(json.dumps({
    "user": user,
    "stories": stories,
}, indent=2))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    main()&lt;/p&gt;

&lt;p&gt;Now the workflow is simply:&lt;/p&gt;

&lt;p&gt;python osint_check.py public_username&lt;/p&gt;

&lt;p&gt;I can pipe the resulting JSON into other tools later if I need to, rather than making the CLI responsible for the entire investigation.&lt;/p&gt;

&lt;p&gt;What I actually wanted from it&lt;/p&gt;

&lt;p&gt;The interesting part for me wasn't "getting Instagram data."&lt;/p&gt;

&lt;p&gt;It was reducing the friction between a research question and a repeatable check.&lt;/p&gt;

&lt;p&gt;For example, when investigating a public account, I might want to answer questions such as:&lt;/p&gt;

&lt;p&gt;Does this username resolve to a public profile?&lt;/p&gt;

&lt;p&gt;What profile information is currently exposed?&lt;/p&gt;

&lt;p&gt;Are there currently available public stories?&lt;/p&gt;

&lt;p&gt;Can I save the API response for later analysis?&lt;/p&gt;

&lt;p&gt;Can I repeat the same check consistently across several public accounts?&lt;/p&gt;

&lt;p&gt;The tool doesn't try to infer someone's identity or make conclusions from the data. It just gives me a structured starting point from publicly accessible information.&lt;/p&gt;

&lt;p&gt;The part that was harder than expected&lt;/p&gt;

&lt;p&gt;The harder part wasn't making the HTTP requests.&lt;/p&gt;

&lt;p&gt;It was keeping the tool's assumptions straight.&lt;/p&gt;

&lt;p&gt;A username and a user ID are not interchangeable, and API responses can contain considerably more information than the small field I initially cared about. Once I started treating the response as structured research data rather than something to immediately print to the terminal, error handling and output structure became much more important.&lt;/p&gt;

&lt;p&gt;I also had to resist the temptation to turn a small script into a giant framework.&lt;/p&gt;

&lt;p&gt;For this use case, a predictable CLI that does a couple of things well is more useful to me than a dashboard full of features I may never use.&lt;/p&gt;

&lt;p&gt;Where I want to take it&lt;/p&gt;

&lt;p&gt;The next useful step would be adding optional JSON output to a file, timestamps for each collection, and a simple way to compare two observations of the same public profile.&lt;/p&gt;

&lt;p&gt;That would make the tool more useful for longitudinal research without changing its basic purpose.&lt;/p&gt;

&lt;p&gt;For now, though, I'm happy with the experiment.&lt;/p&gt;

&lt;p&gt;It's a small Python wrapper around a REST API, but it answers the question I started with: can I make routine public-profile checks quicker and more reproducible without building a whole OSINT platform?&lt;/p&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;And sometimes that's enough for a useful tool.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>python</category>
      <category>security</category>
      <category>tools</category>
    </item>
  </channel>
</rss>
