[Golang] Instagram Topsearch Client


Interesting small program to do Instagram top searches on local machines in Go.

In this program only Go standard library is used, no third-party packages.

To access the Instagram API via local Go program, you need to login Instagram and get the following information from your browser:

  • ds_user_id
  • sessionid
  • csrftoken
ds_user_id sessionid csrftoken

Please see this SO answer to get above values on Chrome browser.

topsearch.go | repository | view raw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
package instago

// This file implements topsearch of Instagram web.

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strconv"
)

const urlTopsearch = `https://www.instagram.com/web/search/topsearch/?query=`

// Decode JSON data returned from Instagram topsearch API
type IGTopsearchResp struct {
	Users []struct {
		Position int64 `json:"position"`
		User     struct {
			Pk               string `json:"pk"`
			Username         string `json:"username"`
			FullName         string `json:"full_name"`
			IsPrivate        bool   `json:"is_private"`
			ProfilePicUrl    string `json:"profile_pic_url"`
			ProfilePicId     string `json:"profile_pic_id"`
			FriendshipStatus struct {
				Following       bool `json:"following"`
				IsPrivate       bool `json:"is_private"`
				IncomingRequest bool `json:"incoming_request"`
				OutgoingRequest bool `json:"outgoing_request"`
				IsBestie        bool `json:"is_bestie"`
			} `json:"friendship_status"`
			IsVerified                 bool    `json:"is_verified"`
			HasAnonymousProfilePicture bool    `json:"has_anonymous_profile_picture"`
			FollowerCount              int64   `json:"follower_count"`
			Byline                     string  `json:"byline"`
			MutualFollowersCount       float64 `json:"mutual_followers_count"`
			LatestReelMedia            int64   `json:"latest_reel_media"`
		} `json:"user"`
	} `json:"users"`

	//TODO: Places ... `json:"places"`

	Hashtags []struct {
		Position int64 `json:"position"`
		Hashtag  struct {
			Name       string `json:"name"`
			Id         int64  `json:"id"`
			MediaCount int64  `json:"media_count"`
		} `json:"hashtag"`
	} `json:"hashtags"`
	HasMore          bool   `json:"has_more"`
	RankToken        string `json:"rank_token"`
	ClearClientCache bool   `json:"clear_client_cache"`
	Status           string `json:"status"`
}

// Send HTTP request and get http response on behalf of a specific Instagram
// user. After login to Instagram, you can get the cookies of *ds_user_id*,
// *sessionid*, *csrftoken* in Chrome Developer Tools.
// See https://stackoverflow.com/a/44773079
// or
// https://github.com/hoschiCZ/instastories-backup#obtain-cookies
func getHTTPResponse(url, ds_user_id, sessionid, csrftoken string) (b []byte, err error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return
	}

	req.AddCookie(&http.Cookie{Name: "ds_user_id", Value: ds_user_id})
	req.AddCookie(&http.Cookie{Name: "sessionid", Value: sessionid})
	req.AddCookie(&http.Cookie{Name: "csrftoken", Value: csrftoken})

	req.Header.Set("User-Agent", "Instagram 10.3.2 (iPhone7,2; iPhone OS 9_3_3; en_US; en-US; scale=2.00; 750x1334) AppleWebKit/420+")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		err = errors.New(
			"resp.StatusCode: " +
				strconv.Itoa(resp.StatusCode))
		return
	}

	return ioutil.ReadAll(resp.Body)
}

// Given a string, return the users that best matches the string. This is
// actually *topsearch* on Instagram web.
func Topsearch(str, ds_user_id, sessionid, csrftoken string) (tr IGTopsearchResp, err error) {
	url := urlTopsearch + str
	b, err := getHTTPResponse(url, ds_user_id, sessionid, csrftoken)
	if err != nil {
		return
	}

	err = json.Unmarshal(b, &tr)
	return
}

Example:

topsearch_test.go | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package instago

import (
	"os"
	"testing"
)

func ExampleTopsearch(t *testing.T) {
	tr, err := Topsearch("instagram",
		os.Getenv("IG_DS_USER_ID"),
		os.Getenv("IG_SESSIONID"),
		os.Getenv("IG_CSRFTOKEN"))
	if err != nil {
		t.Error(err)
		return
	}
	t.Log(tr)
}

The full code is also available on my GitHub repo [1].


Tested on: Ubuntu Linux 17.10, Go 1.9.4.


References:

[1]GitHub - siongui/instago: Get photos, videos, stories, following and followers of Instagram