Instagram offers two kinds of APIs to developers. The Instagram API Platform (extremely limited in functionality and close to being discontinued), and the Instagram Graph API for Business and Creator accounts only.
However, Instagram apps rely on a third type of API, the so-called Private API or Unofficial API, and SwiftyInsta is an iOS, macOS, tvOS and watchOS client for them, written entirely in Swift. You can try and create a better Instagram experience for your users, or write bots for automating different tasks.
These Private API require no token or app registration but they’re not authorized by Instagram for external use. Use this at your own risk.
Installation
Swift Package Manager (Xcode 11 and above)
File
/Swift Packages
/Add Package Dependency
…
from the menu.https://github.com/TheM4hd1/SwiftyInsta.git
.CocoaPods
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
$ gem install cocoapods
To integrate SwiftyInsta into your Xcode project using CocoaPods, specify it in your Podfile
:
use_frameworks!
target ‘<Your Target Name>’ do
pod ‘SwiftyInsta’, ‘~> 2.0’
end
Then, run the following command:
$ pod install
SwiftyInsta depends on CryptoSwift and keychain-swift.
Login
Credentials
// these need to be strong references. self.credentials = Credentials(username: /* username */, password: /* password */, verifyBy: .text) self.handler = APIHandler() handler.authenticate(with: .user(credentials)) { switch $0 { case .success(let response, _): print("Login successful.") // persist cache safely in the keychain for logging in again in the future. guard let key = response.persist() else { return print("`Authentication.Response` could not be persisted.") } // store the `key` wherever you want, so you can access the `Authentication.Response` later. // `UserDefaults` is just an example. UserDefaults.standard.set(key, forKey: "current.account") UserDefaults.standard.synchronize() case .failure(let error): if error.requiresInstagramCode { /* update interface to ask for code */ } else { /* notify the user */ } } }
Once the user has typed the two factor authentication code or challenge code, you simply do
self.credentials.code = /* the code */
And the completionHandler
in the previous authenticate(with: completionHandler:)
will automatically catch the response.
LoginWebViewController
(>= iOS 12 only)
let login = LoginWebViewController { controller, result in controller.dismiss(animated: true, completion: nil) // deal with authentication response. guard let (response, _) = try? result.get() else { return print("Login failed.") } print("Login successful.") // persist cache safely in the keychain for logging in again in the future. guard let key = response.persist() else { return print("`Authentication.Response` could not be persisted.") } // store the `key` wherever you want, so you can access the `Authentication.Response` later. // `UserDefaults` is just an example. UserDefaults.standard.set(key, forKey: "current.account") UserDefaults.standard.synchronize() } if #available(iOS 13, *) { present(login, animated: true, completion: nil) // just swipe down to dismiss. } else { present(UINavigationController(rootViewController: login), // already adds a `Cancel` button to dismiss it. animated: true, completion: nil) }
Or implement your own custom UIViewController
using LoginWebView
, and pass it to an APIHandler
authenticate
method using .webView(/* your login web view */)
.
Authentication.Response
If you’ve already persisted a user’s Authentication.Response
:
// recover the `key` returned by `Authentication.Response.persist()`. // in our example, we stored it in `UserDefaults`. guard let key = UserDefaults.standard.string(forKey: "current.account") else { return print("`key` not found.") } // recover the safely persisted `Authentication.Response`. guard let cache = Authentication.Response.persisted(with: key) else { return print("`Authentication.Response` not found.") } // log in. let handler = APIHandler() handler.authenticate(with: .cache(cache)) { _ in /* do something here */}
Usage
All endpoints are easily accessible from your APIHandler
instance.
let handler: APIHandler = /* a valid, authenticated handler */// for instance you can… // …fetch your inbox. handler.messages.inbox(with: .init(maxPagesToLoad: .max), updateHandler: nil, completionHandler: { _, _ in /* do something */ }) // …fetch all your followers. handler.users.following(user: .me, with: .init(maxPagesToLoad: .max), updateHandler: nil, completionHandler: { _, _ in /* do something */ })
Futhermore, responses now display every single value contained in the JSON
file returned by the API: just access any ParsedResponse
rawResponse
and start browsing, or stick with the suggested accessories (e.g. User
‘s username
, name
, etc. and Media
‘s aspectRatio
, takenAt
, content
, etc.).
shadow-rs is a Windows kernel rootkit written in Rust, demonstrating advanced techniques for kernel manipulation…
Extract and execute a PE embedded within a PNG file using an LNK file. The…
Embark on the journey of becoming a certified Red Team professional with our definitive guide.…
This repository contains proof of concept exploits for CVE-2024-5836 and CVE-2024-6778, which are vulnerabilities within…
This took me like 4 days (+2 days for an update), but I got it…
MaLDAPtive is a framework for LDAP SearchFilter parsing, obfuscation, deobfuscation and detection. Its foundation is…