Documentation
¶
Overview ¶
Package sinac is the Go client for the ScrapingIsNotACrime API (https://scrapingisnotacrime.com): public data from Instagram, TikTok, YouTube, the App Store, GitHub, Hacker News, Bluesky, Twitch and Linktree.
import sinac "github.com/ScrapingIsNotACrime/sdk-go"
client, err := sinac.NewClient(sinac.WithAPIKey("sinac_..."))
profile, err := client.Instagram.Profile(ctx, "nasa")
Errors are *Error values matched with errors.Is against the Err* sentinels. Paginated methods return a *Page; Page.All iterates every item lazily, and each page fetched is one billed request.
Example ¶
package main
import (
"context"
"errors"
"fmt"
"log"
sinac "github.com/ScrapingIsNotACrime/sdk-go"
)
func main() {
client, err := sinac.NewClient(sinac.WithAPIKey("sinac_..."))
if err != nil {
log.Fatal(err)
}
profile, err := client.Instagram.Profile(context.Background(), "nasa")
if errors.Is(err, sinac.ErrNotFound) {
fmt.Println("no such profile")
return
}
if err != nil {
log.Fatal(err)
}
fmt.Println(profile.Username, profile.Followers)
}
Output:
Index ¶
- Constants
- Variables
- type AppStoreApp
- type AppStoreReview
- type AppStoreReviewPage
- type AppStoreReviewsParams
- type AppStoreSearch
- type AppStoreSearchParams
- type AppStoreService
- type BlueskyPost
- type BlueskyPostPage
- type BlueskyPostsParams
- type BlueskyProfile
- type BlueskyService
- type Client
- type Error
- type GitHubListParams
- type GitHubProfile
- type GitHubRepository
- type GitHubRepositoryPage
- type GitHubRepositorySearchPage
- type GitHubService
- func (s *GitHubService) Followers(ctx context.Context, handle string, p *GitHubListParams) (*Page[GitHubUser, GitHubUserPage], error)
- func (s *GitHubService) Following(ctx context.Context, handle string, p *GitHubListParams) (*Page[GitHubUser, GitHubUserPage], error)
- func (s *GitHubService) Profile(ctx context.Context, handle string) (*GitHubProfile, error)
- func (s *GitHubService) Repositories(ctx context.Context, handle string, p *GitHubListParams) (*Page[GitHubRepository, GitHubRepositoryPage], error)
- func (s *GitHubService) SearchRepositories(ctx context.Context, q string, p *GitHubListParams) (*Page[GitHubRepository, GitHubRepositorySearchPage], error)
- func (s *GitHubService) Trending(ctx context.Context, p *GitHubTrendingParams) (*GitHubTrending, error)
- type GitHubTrending
- type GitHubTrendingParams
- type GitHubTrendingSince
- type GitHubUser
- type GitHubUserPage
- type HackerNewsComment
- type HackerNewsFeed
- type HackerNewsItem
- type HackerNewsListParams
- type HackerNewsService
- func (s *HackerNewsService) Comments(ctx context.Context, username string, p *HackerNewsListParams) (*Page[HackerNewsUserComment, HackerNewsUserCommentPage], error)
- func (s *HackerNewsService) Feed(ctx context.Context, feed HackerNewsFeed, p *HackerNewsListParams) (*Page[HackerNewsStory, HackerNewsStoryPage], error)
- func (s *HackerNewsService) Item(ctx context.Context, id int64) (*HackerNewsItem, error)
- func (s *HackerNewsService) Search(ctx context.Context, q string, p *HackerNewsListParams) (*Page[HackerNewsStory, HackerNewsStoryPage], error)
- func (s *HackerNewsService) Submissions(ctx context.Context, username string, p *HackerNewsListParams) (*Page[HackerNewsStory, HackerNewsStoryPage], error)
- func (s *HackerNewsService) User(ctx context.Context, username string) (*HackerNewsUser, error)
- type HackerNewsStory
- type HackerNewsStoryPage
- type HackerNewsUser
- type HackerNewsUserComment
- type HackerNewsUserCommentPage
- type InstagramClipsMusicAttribution
- type InstagramContact
- type InstagramContactAddress
- type InstagramDownload
- type InstagramDownloadAsset
- type InstagramFoundContact
- type InstagramHighlight
- type InstagramHighlightSummary
- type InstagramHighlights
- type InstagramLatestPostMedia
- type InstagramLatestPosts
- type InstagramMedia
- type InstagramMediaDetail
- type InstagramPostsParams
- type InstagramProfile
- type InstagramReel
- type InstagramService
- func (s *InstagramService) Contact(ctx context.Context, username string) (*InstagramContact, error)
- func (s *InstagramService) Download(ctx context.Context, shortcode string) (*InstagramDownload, error)
- func (s *InstagramService) Highlight(ctx context.Context, highlightID string) (*InstagramHighlight, error)
- func (s *InstagramService) Highlights(ctx context.Context, username string) (*InstagramHighlights, error)
- func (s *InstagramService) IDToShortcode(ctx context.Context, mediaID string) (*InstagramShortcodeID, error)
- func (s *InstagramService) LatestPosts(ctx context.Context, username string) (*InstagramLatestPosts, error)
- func (s *InstagramService) Media(ctx context.Context, shortcode string) (*InstagramMediaDetail, error)
- func (s *InstagramService) MediaByID(ctx context.Context, username, mediaID string) (*InstagramMediaDetail, error)
- func (s *InstagramService) Posts(ctx context.Context, username string, p *InstagramPostsParams) (*Page[InstagramMedia, InstagramTimelinePage], error)
- func (s *InstagramService) Profile(ctx context.Context, username string) (*InstagramProfile, error)
- func (s *InstagramService) Reel(ctx context.Context, shortcode string) (*InstagramReel, error)
- func (s *InstagramService) ShortcodeToID(ctx context.Context, shortcode string) (*InstagramShortcodeID, error)
- type InstagramShortcodeID
- type InstagramTimelinePage
- type LinktreeLink
- type LinktreeProfile
- type LinktreeService
- type Option
- type Page
- type TikTokProfile
- type TikTokService
- type TikTokVideo
- type TwitchBroadcast
- type TwitchProfile
- type TwitchService
- type TwitchVideo
- type TwitchVideos
- type TwitchVideosParams
- type YouTubeChannel
- type YouTubeChannelVideos
- type YouTubeService
- type YouTubeVideo
Examples ¶
Constants ¶
const ( // DefaultBaseURL is the production API. DefaultBaseURL = "https://api.scrapingisnotacrime.com/v1" // APIKeyEnv is read when WithAPIKey is not given. APIKeyEnv = "SCRAPINGISNOTACRIME_API_KEY" // DefaultTimeout bounds each attempt: connect, headers and body. DefaultTimeout = 30 * time.Second // DefaultMaxRetries is the number of extra attempts for 429, 502 and network errors. DefaultMaxRetries = 2 )
const PricingURL = "https://scrapingisnotacrime.com/#pricing"
PricingURL is appended to quota-exceeded messages.
Variables ¶
var ( ErrBadRequest = errors.New("sinac: bad request") // 400, or an invalid path argument ErrAuthentication = errors.New("sinac: authentication failed") // 401 ErrQuotaExceeded = errors.New("sinac: quota exceeded") // 402 ErrNotFound = errors.New("sinac: not found") // 404 ErrRateLimit = errors.New("sinac: rate limited") // 429, retried, not charged ErrUpstream = errors.New("sinac: upstream failure") // 502, retried, not charged ErrConnection = errors.New("sinac: connection error") // network failure or timeout, retried ErrAPI = errors.New("sinac: API error") // anything else )
Sentinel kinds, matched with errors.Is on any error the client returns.
var Version = moduleVersion()
Version is this module's version as recorded in the importing program's build info (for example "0.1.0"), or "dev" when it is unknown.
Functions ¶
This section is empty.
Types ¶
type AppStoreApp ¶
type AppStoreApp struct {
ID int64 `json:"id"`
BundleID string `json:"bundleId"`
Name string `json:"name"`
Developer string `json:"developer"`
URL string `json:"url"`
IconURL string `json:"iconUrl"`
Price float64 `json:"price"`
Currency string `json:"currency"`
Rating float64 `json:"rating"`
RatingCount int64 `json:"ratingCount"`
Version string `json:"version"`
Genres []string `json:"genres"`
Screenshots []string `json:"screenshots"`
}
AppStoreApp is one app in an App Store search result.
type AppStoreReview ¶
type AppStoreReview struct {
ID string `json:"id"`
Author string `json:"author"`
Rating float64 `json:"rating"`
Title string `json:"title"`
Content string `json:"content"`
Version string `json:"version"`
UpdatedAt string `json:"updatedAt"`
VoteCount int64 `json:"voteCount"`
VoteSum int64 `json:"voteSum"`
}
AppStoreReview is one customer review of an app.
type AppStoreReviewPage ¶
type AppStoreReviewPage struct {
AppID string `json:"appId"`
Country string `json:"country"`
Page int64 `json:"page"`
Reviews []AppStoreReview `json:"reviews"`
}
AppStoreReviewPage is GET /appstore/reviews.
type AppStoreReviewsParams ¶
AppStoreReviewsParams: Country (default "us"); Page 1-10 (default 1).
type AppStoreSearch ¶
type AppStoreSearch struct {
Term string `json:"term"`
Country string `json:"country"`
ResultCount int64 `json:"resultCount"`
Apps []AppStoreApp `json:"apps"`
}
AppStoreSearch is GET /appstore/search.
type AppStoreSearchParams ¶
AppStoreSearchParams: Country is a two-letter store code (default "us"); Limit 1-200 (default 10).
type AppStoreService ¶
type AppStoreService struct {
// contains filtered or unexported fields
}
AppStoreService groups the App Store endpoints.
func (*AppStoreService) Reviews ¶
func (s *AppStoreService) Reviews(ctx context.Context, appID string, p *AppStoreReviewsParams) (*Page[AppStoreReview, AppStoreReviewPage], error)
Reviews is GET /appstore/reviews — pages 1-10 (Apple's cap); the API returns 400 past page 10.
func (*AppStoreService) Search ¶
func (s *AppStoreService) Search(ctx context.Context, term string, p *AppStoreSearchParams) (*AppStoreSearch, error)
Search is GET /appstore/search — Country defaults to "us", Limit 1-200 (default 10).
type BlueskyPost ¶
type BlueskyPost struct {
URI string `json:"uri"`
CID string `json:"cid"`
Text string `json:"text"`
Author string `json:"author"`
Likes int64 `json:"likes"`
Reposts int64 `json:"reposts"`
Replies int64 `json:"replies"`
Quotes int64 `json:"quotes"`
CreatedAt string `json:"created_at"`
IndexedAt string `json:"indexed_at"`
URL string `json:"url"`
}
BlueskyPost is one post in a profile's posts feed.
type BlueskyPostPage ¶
type BlueskyPostPage struct {
Posts []BlueskyPost `json:"posts"`
NextCursor *string `json:"next_cursor,omitempty"`
HasMore bool `json:"has_more"`
}
BlueskyPostPage is GET /bluesky/profiles/{handle}/posts.
type BlueskyPostsParams ¶
BlueskyPostsParams: Limit 1-100 (default 25); Cursor from Page.NextCursor.
type BlueskyProfile ¶
type BlueskyProfile struct {
DID string `json:"did"`
Handle string `json:"handle"`
DisplayName string `json:"display_name"`
// Null when the profile has no bio.
Description *string `json:"description,omitempty"`
// Null when the profile has no avatar set.
Avatar *string `json:"avatar,omitempty"`
// Banner image URL; null when the profile has none set.
Banner *string `json:"banner,omitempty"`
Followers int64 `json:"followers"`
Following int64 `json:"following"`
Posts int64 `json:"posts"`
CreatedAt string `json:"created_at"`
URL string `json:"url"`
}
BlueskyProfile is GET /bluesky/profiles/{handle}.
type BlueskyService ¶
type BlueskyService struct {
// contains filtered or unexported fields
}
BlueskyService groups the Bluesky endpoints.
func (*BlueskyService) Posts ¶
func (s *BlueskyService) Posts(ctx context.Context, handle string, p *BlueskyPostsParams) (*Page[BlueskyPost, BlueskyPostPage], error)
Posts is GET /bluesky/profiles/{handle}/posts — limit 1-100 (default 25), cursor-paginated.
func (*BlueskyService) Profile ¶
func (s *BlueskyService) Profile(ctx context.Context, handle string) (*BlueskyProfile, error)
Profile is GET /bluesky/profiles/{handle} — full handle including the domain.
type Client ¶
type Client struct {
Instagram *InstagramService
TikTok *TikTokService
YouTube *YouTubeService
AppStore *AppStoreService
GitHub *GitHubService
HackerNews *HackerNewsService
Bluesky *BlueskyService
Twitch *TwitchService
Linktree *LinktreeService
}
Client is the ScrapingIsNotACrime API client. It is safe for concurrent use.
type Error ¶
type Error struct {
Status int // HTTP status; 0 when there was no response
Message string // the API's message, or a description of the failure
RequestID string // the x-request-id header, "" when absent
// contains filtered or unexported fields
}
Error is returned for every API, network and argument failure.
type GitHubListParams ¶
GitHubListParams: Limit 1-100 (default 30); Page is 1-based (default 1).
type GitHubProfile ¶
type GitHubProfile struct {
Username string `json:"username"`
ID int64 `json:"id"`
// Null when the user has not set a display name.
Name *string `json:"name,omitempty"`
// Null when the user has not set a bio.
Bio *string `json:"bio,omitempty"`
Company *string `json:"company,omitempty"`
Location *string `json:"location,omitempty"`
// Website URL; empty or null when the user has not set one.
Blog *string `json:"blog,omitempty"`
PublicRepos int64 `json:"public_repos"`
Followers int64 `json:"followers"`
Following int64 `json:"following"`
Avatar string `json:"avatar"`
CreatedAt string `json:"created_at"`
URL string `json:"url"`
}
GitHubProfile is GET /github/profiles/{handle}.
type GitHubRepository ¶
type GitHubRepository struct {
Name string `json:"name"`
FullName string `json:"full_name"`
// Null when the repository has no description.
Description *string `json:"description,omitempty"`
Stars int64 `json:"stars"`
Forks int64 `json:"forks"`
// Primary language; null when GitHub has not detected one.
Language *string `json:"language,omitempty"`
Topics []string `json:"topics"`
IsFork bool `json:"is_fork"`
IsArchived bool `json:"is_archived"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
URL string `json:"url"`
}
GitHubRepository is a repository, as returned by the profile repositories list, search, and trending endpoints.
type GitHubRepositoryPage ¶
type GitHubRepositoryPage struct {
Items []GitHubRepository `json:"items"`
// Always null: GitHub's REST API does not report a count for this collection.
Total *int64 `json:"total,omitempty"`
HasMore bool `json:"has_more"`
}
GitHubRepositoryPage is GET /github/profiles/{handle}/repositories.
type GitHubRepositorySearchPage ¶
type GitHubRepositorySearchPage struct {
Items []GitHubRepository `json:"items"`
Total int64 `json:"total"`
Page int64 `json:"page"`
HasMore bool `json:"has_more"`
}
GitHubRepositorySearchPage is GET /github/repositories.
type GitHubService ¶
type GitHubService struct {
// contains filtered or unexported fields
}
GitHubService groups the GitHub endpoints.
func (*GitHubService) Followers ¶
func (s *GitHubService) Followers(ctx context.Context, handle string, p *GitHubListParams) (*Page[GitHubUser, GitHubUserPage], error)
Followers is GET /github/profiles/{handle}/followers — limit 1-100 (default 30), 1-based pages.
func (*GitHubService) Following ¶
func (s *GitHubService) Following(ctx context.Context, handle string, p *GitHubListParams) (*Page[GitHubUser, GitHubUserPage], error)
Following is GET /github/profiles/{handle}/following — limit 1-100 (default 30), 1-based pages.
func (*GitHubService) Profile ¶
func (s *GitHubService) Profile(ctx context.Context, handle string) (*GitHubProfile, error)
Profile is GET /github/profiles/{handle}.
func (*GitHubService) Repositories ¶
func (s *GitHubService) Repositories(ctx context.Context, handle string, p *GitHubListParams) (*Page[GitHubRepository, GitHubRepositoryPage], error)
Repositories is GET /github/profiles/{handle}/repositories — limit 1-100 (default 30), 1-based pages.
func (*GitHubService) SearchRepositories ¶
func (s *GitHubService) SearchRepositories(ctx context.Context, q string, p *GitHubListParams) (*Page[GitHubRepository, GitHubRepositorySearchPage], error)
SearchRepositories is GET /github/repositories — q in GitHub search syntax; limit 1-100 (default 30), 1-based pages.
func (*GitHubService) Trending ¶
func (s *GitHubService) Trending(ctx context.Context, p *GitHubTrendingParams) (*GitHubTrending, error)
Trending is GET /github/trending/repositories — Since defaults to "daily"; Limit 1-100 (default 30). Not paginated.
type GitHubTrending ¶
type GitHubTrending struct {
Items []GitHubRepository `json:"items"`
Total int64 `json:"total"`
Page int64 `json:"page"`
HasMore bool `json:"has_more"`
}
GitHubTrending is GET /github/trending/repositories.
type GitHubTrendingParams ¶
type GitHubTrendingParams struct {
Since GitHubTrendingSince
Language string
Limit int
}
GitHubTrendingParams: Since (default daily), Language (e.g. "go"), Limit 1-100 (default 30).
type GitHubTrendingSince ¶
type GitHubTrendingSince string
GitHubTrendingSince is the period of GitHub's trending list.
const ( TrendingDaily GitHubTrendingSince = "daily" TrendingWeekly GitHubTrendingSince = "weekly" TrendingMonthly GitHubTrendingSince = "monthly" )
type GitHubUser ¶
type GitHubUser struct {
Username string `json:"username"`
ID int64 `json:"id"`
Avatar string `json:"avatar"`
URL string `json:"url"`
}
GitHubUser is a user in a followers/following page.
type GitHubUserPage ¶
type GitHubUserPage struct {
Items []GitHubUser `json:"items"`
// Always null: GitHub's REST API does not report a count for this collection.
Total *int64 `json:"total,omitempty"`
HasMore bool `json:"has_more"`
}
GitHubUserPage is GET /github/profiles/{handle}/followers and /following.
type HackerNewsComment ¶
type HackerNewsComment struct {
ID int64 `json:"id"`
Author string `json:"author"`
Text string `json:"text"`
CreatedAt string `json:"created_at"`
Replies []HackerNewsComment `json:"replies"`
}
HackerNewsComment is a comment inside an item's comment tree; replies nest recursively.
type HackerNewsFeed ¶
type HackerNewsFeed string
HackerNewsFeed is one of Hacker News' story lists.
const ( FeedTop HackerNewsFeed = "top" FeedNew HackerNewsFeed = "new" FeedBest HackerNewsFeed = "best" FeedAsk HackerNewsFeed = "ask" FeedShow HackerNewsFeed = "show" FeedJob HackerNewsFeed = "job" )
type HackerNewsItem ¶
type HackerNewsItem struct {
ID int64 `json:"id"`
Type string `json:"type"`
// Null for comments and other untitled item types.
Title *string `json:"title,omitempty"`
Author string `json:"author"`
Points *int64 `json:"points,omitempty"`
// External link; null for self-posts.
URL *string `json:"url,omitempty"`
// Self-post body as HTML; null for link posts.
Text *string `json:"text,omitempty"`
CreatedAt string `json:"created_at"`
HNURL string `json:"hn_url"`
Comments []HackerNewsComment `json:"comments"`
}
HackerNewsItem is GET /hackernews/items/{id}.
type HackerNewsListParams ¶
HackerNewsListParams: Limit 1-50 (default 20); Page is 0-based (default 0).
type HackerNewsService ¶
type HackerNewsService struct {
// contains filtered or unexported fields
}
HackerNewsService groups the Hacker News endpoints.
func (*HackerNewsService) Comments ¶
func (s *HackerNewsService) Comments(ctx context.Context, username string, p *HackerNewsListParams) (*Page[HackerNewsUserComment, HackerNewsUserCommentPage], error)
Comments is GET /hackernews/users/{username}/comments — limit 1-50 (default 20), 0-based pages.
func (*HackerNewsService) Feed ¶
func (s *HackerNewsService) Feed(ctx context.Context, feed HackerNewsFeed, p *HackerNewsListParams) (*Page[HackerNewsStory, HackerNewsStoryPage], error)
Feed is GET /hackernews/feeds/{feed} — limit 1-50 (default 20), 0-based pages.
func (*HackerNewsService) Item ¶
func (s *HackerNewsService) Item(ctx context.Context, id int64) (*HackerNewsItem, error)
Item is GET /hackernews/items/{id} — the item with its full comment tree.
func (*HackerNewsService) Search ¶
func (s *HackerNewsService) Search(ctx context.Context, q string, p *HackerNewsListParams) (*Page[HackerNewsStory, HackerNewsStoryPage], error)
Search is GET /hackernews/search — limit 1-50 (default 20), 0-based pages.
func (*HackerNewsService) Submissions ¶
func (s *HackerNewsService) Submissions(ctx context.Context, username string, p *HackerNewsListParams) (*Page[HackerNewsStory, HackerNewsStoryPage], error)
Submissions is GET /hackernews/users/{username}/submissions — limit 1-50 (default 20), 0-based pages.
func (*HackerNewsService) User ¶
func (s *HackerNewsService) User(ctx context.Context, username string) (*HackerNewsUser, error)
User is GET /hackernews/users/{username}.
type HackerNewsStory ¶
type HackerNewsStory struct {
ID int64 `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
Points int64 `json:"points"`
NumComments int64 `json:"num_comments"`
// External link; null for self-posts (Ask HN, etc.).
URL *string `json:"url,omitempty"`
// Self-post body as HTML; null for link posts.
Text *string `json:"text,omitempty"`
CreatedAt string `json:"created_at"`
HNURL string `json:"hn_url"`
}
HackerNewsStory is a story, as returned by feeds, search, and a user's submissions.
type HackerNewsStoryPage ¶
type HackerNewsStoryPage struct {
Items []HackerNewsStory `json:"items"`
Total int64 `json:"total"`
Page int64 `json:"page"`
HasMore bool `json:"has_more"`
}
HackerNewsStoryPage is GET /hackernews/feeds/{feed}, /hackernews/search, and /hackernews/users/{username}/submissions.
type HackerNewsUser ¶
type HackerNewsUser struct {
Username string `json:"username"`
Karma int64 `json:"karma"`
// Profile bio as HTML; null when the user has not written one.
About *string `json:"about,omitempty"`
CreatedAt string `json:"created_at"`
SubmissionCount int64 `json:"submission_count"`
HNURL string `json:"hn_url"`
}
HackerNewsUser is GET /hackernews/users/{username}.
type HackerNewsUserComment ¶
type HackerNewsUserComment struct {
ID int64 `json:"id"`
Author string `json:"author"`
Text string `json:"text"`
CreatedAt string `json:"created_at"`
Replies []HackerNewsComment `json:"replies,omitempty"`
}
HackerNewsUserComment is a comment in a user's comment listing; unlike item-tree nodes, Replies may be absent.
type HackerNewsUserCommentPage ¶
type HackerNewsUserCommentPage struct {
Items []HackerNewsUserComment `json:"items"`
Total int64 `json:"total"`
Page int64 `json:"page"`
HasMore bool `json:"has_more"`
}
HackerNewsUserCommentPage is GET /hackernews/users/{username}/comments — same page envelope as the other listings.
type InstagramClipsMusicAttribution ¶
type InstagramClipsMusicAttribution struct {
ArtistName string `json:"artist_name"`
SongName string `json:"song_name"`
UsesOriginalAudio bool `json:"uses_original_audio"`
}
InstagramClipsMusicAttribution is music attribution for a video/reel; null for original audio.
type InstagramContact ¶
type InstagramContact struct {
Username string `json:"username"`
FullName string `json:"full_name"`
Biography string `json:"biography"`
IsVerified bool `json:"is_verified"`
IsBusiness bool `json:"is_business"`
Category string `json:"category"`
Email *string `json:"email,omitempty"`
Phone *string `json:"phone,omitempty"`
ExternalURL string `json:"external_url"`
// Null for a profile with no contact information (per the endpoint's docs, all fields in that case are null).
Address *InstagramContactAddress `json:"address,omitempty"`
EmailsFound []InstagramFoundContact `json:"emails_found"`
PhonesFound []InstagramFoundContact `json:"phones_found"`
}
InstagramContact is GET /instagram/profile/{username}/contact.
type InstagramContactAddress ¶
type InstagramContactAddress struct {
StreetAddress string `json:"street_address"`
ZipCode string `json:"zip_code"`
CityName string `json:"city_name"`
RegionName string `json:"region_name"`
CountryCode string `json:"country_code"`
}
InstagramContactAddress is a profile's structured business address, from the contact endpoint.
type InstagramDownload ¶
type InstagramDownload struct {
Shortcode string `json:"shortcode"`
Type string `json:"type"`
ExpiresAt string `json:"expires_at"`
Assets []InstagramDownloadAsset `json:"assets"`
}
InstagramDownload is GET /instagram/media/{shortcode}/download — assets[0] is always the best primary asset.
type InstagramDownloadAsset ¶
type InstagramDownloadAsset struct {
Kind string `json:"kind"`
Index int64 `json:"index"`
URL string `json:"url"`
Width int64 `json:"width"`
Height int64 `json:"height"`
// Null for non-video assets (e.g. thumbnails).
Quality *string `json:"quality,omitempty"`
ExpiresAt string `json:"expires_at"`
}
InstagramDownloadAsset is one downloadable asset behind a post, reel, or carousel.
type InstagramFoundContact ¶
InstagramFoundContact is an email address or phone number found written into a profile's bio.
type InstagramHighlight ¶
type InstagramHighlight struct {
ID string `json:"id"`
Title string `json:"title"`
Items []InstagramMedia `json:"items"`
}
InstagramHighlight is GET /instagram/highlights/{highlightId}.
type InstagramHighlightSummary ¶
type InstagramHighlightSummary struct {
ID string `json:"id"`
Title string `json:"title"`
Cover string `json:"cover"`
}
InstagramHighlightSummary is a highlight reel's summary, as listed on a profile.
type InstagramHighlights ¶
type InstagramHighlights struct {
Username string `json:"username"`
UserID string `json:"user_id"`
Highlights []InstagramHighlightSummary `json:"highlights"`
}
InstagramHighlights is GET /instagram/profile/{username}/highlights.
type InstagramLatestPostMedia ¶
type InstagramLatestPostMedia struct {
ID string `json:"id"`
Shortcode string `json:"shortcode"`
Type string `json:"type"`
// Video-only field.
VideoViews *int64 `json:"video_views,omitempty"`
Comments int64 `json:"comments"`
Likes int64 `json:"likes"`
// Null when the post has no caption.
Caption *string `json:"caption,omitempty"`
Location any `json:"location,omitempty"`
ThumbnailResources any `json:"thumbnail_resources,omitempty"`
DisplayURL string `json:"display_url"`
// Video-only field.
VideoURL *string `json:"video_url,omitempty"`
// Video-only field.
HasAudio *bool `json:"has_audio,omitempty"`
// Video-only field.
ClipsMusicAttributionInfo *InstagramClipsMusicAttribution `json:"clips_music_attribution_info,omitempty"`
TakenAtTimestamp string `json:"taken_at_timestamp"`
}
InstagramLatestPostMedia is a post in a profile's latest-posts timeline — an image post or a video post; Type tells them apart. Video-only fields (VideoViews, VideoURL, HasAudio, ClipsMusicAttributionInfo) are nil for image posts.
type InstagramLatestPosts ¶
type InstagramLatestPosts struct {
Count int64 `json:"count"`
LatestCount int64 `json:"latest_count"`
Medias []InstagramLatestPostMedia `json:"medias"`
}
InstagramLatestPosts is GET /instagram/profile/{username}/timeline/latest.
type InstagramMedia ¶
type InstagramMedia struct {
ID string `json:"id"`
Shortcode string `json:"shortcode"`
Type string `json:"type"`
// Null when the post has no caption.
Caption *string `json:"caption,omitempty"`
Likes int64 `json:"likes"`
Comments int64 `json:"comments"`
PreviewComments []any `json:"preview_comments"`
Location any `json:"location,omitempty"`
DisplayURL string `json:"display_url"`
TakenAtTimestamp string `json:"taken_at_timestamp"`
}
InstagramMedia is a post, as returned by the paged timeline and the highlight-content endpoints.
type InstagramMediaDetail ¶
type InstagramMediaDetail struct {
ID string `json:"id"`
Shortcode string `json:"shortcode"`
Type string `json:"type"`
Comments int64 `json:"comments"`
Likes int64 `json:"likes"`
// Null when the post has no caption.
Caption *string `json:"caption,omitempty"`
Location any `json:"location,omitempty"`
ThumbnailResources any `json:"thumbnail_resources,omitempty"`
DisplayURL string `json:"display_url"`
TakenAtTimestamp string `json:"taken_at_timestamp"`
VideoViews *int64 `json:"video_views,omitempty"`
VideoURL *string `json:"video_url,omitempty"`
HasAudio *bool `json:"has_audio,omitempty"`
ClipsMusicAttributionInfo *InstagramClipsMusicAttribution `json:"clips_music_attribution_info,omitempty"`
}
InstagramMediaDetail is GET /instagram/profile/{username}/media/{mediaId} — the same media object the timeline endpoints return, including the video-only fields when the media is a video.
type InstagramPostsParams ¶
InstagramPostsParams: Count 1-50 (default 12); Cursor from Page.NextCursor.
type InstagramProfile ¶
type InstagramProfile struct {
ID string `json:"id"`
FBID string `json:"fbid"`
Username string `json:"username"`
FullName string `json:"full_name"`
Bio string `json:"bio"`
BioLinks []string `json:"bio_links"`
Followers int64 `json:"followers"`
Following int64 `json:"following"`
Medias int64 `json:"medias"`
HighlightReelCount int64 `json:"highlight_reel_count"`
ProfilePic string `json:"profile_pic"`
HasAREffects bool `json:"has_ar_effects"`
HasClips bool `json:"has_clips"`
HasGuides bool `json:"has_guides"`
HasChannel bool `json:"has_channel"`
HasBlockedViewer bool `json:"has_blocked_viewer"`
IsBusinessAccount bool `json:"is_business_account"`
// Null in every observed example; no evidence of its populated shape.
BusinessAddressJSON any `json:"business_address_json,omitempty"`
BusinessContactMethod string `json:"business_contact_method"`
BusinessEmail *string `json:"business_email,omitempty"`
BusinessPhoneNumber *string `json:"business_phone_number,omitempty"`
BusinessCategoryName string `json:"business_category_name"`
IsProfessionalAccount bool `json:"is_professional_account"`
CategoryName string `json:"category_name"`
IsPrivate bool `json:"is_private"`
IsVerified bool `json:"is_verified"`
}
InstagramProfile is GET /instagram/profile/{username}.
type InstagramReel ¶
type InstagramReel struct {
ID string `json:"id"`
Shortcode string `json:"shortcode"`
Type string `json:"type"`
VideoViews int64 `json:"video_views"`
Comments int64 `json:"comments"`
Likes int64 `json:"likes"`
// Null when the post has no caption.
Caption *string `json:"caption,omitempty"`
Location any `json:"location,omitempty"`
ThumbnailResources any `json:"thumbnail_resources,omitempty"`
DisplayURL string `json:"display_url"`
VideoURL string `json:"video_url"`
HasAudio bool `json:"has_audio"`
ClipsMusicAttributionInfo *InstagramClipsMusicAttribution `json:"clips_music_attribution_info,omitempty"`
TakenAtTimestamp string `json:"taken_at_timestamp"`
}
InstagramReel is GET /instagram/reels/{shortcode} — clips_music_attribution_info is null for original audio.
type InstagramService ¶
type InstagramService struct {
// contains filtered or unexported fields
}
InstagramService groups the Instagram endpoints.
func (*InstagramService) Contact ¶
func (s *InstagramService) Contact(ctx context.Context, username string) (*InstagramContact, error)
Contact is GET /instagram/profile/{username}/contact — public business contact (email, phone, address).
func (*InstagramService) Download ¶
func (s *InstagramService) Download(ctx context.Context, shortcode string) (*InstagramDownload, error)
Download is GET /instagram/media/{shortcode}/download — assets[0] is the best primary asset.
func (*InstagramService) Highlight ¶
func (s *InstagramService) Highlight(ctx context.Context, highlightID string) (*InstagramHighlight, error)
Highlight is GET /instagram/highlights/{highlightId}.
func (*InstagramService) Highlights ¶
func (s *InstagramService) Highlights(ctx context.Context, username string) (*InstagramHighlights, error)
Highlights is GET /instagram/profile/{username}/highlights.
func (*InstagramService) IDToShortcode ¶
func (s *InstagramService) IDToShortcode(ctx context.Context, mediaID string) (*InstagramShortcodeID, error)
IDToShortcode is GET /instagram/media/id/{mediaId}.
func (*InstagramService) LatestPosts ¶
func (s *InstagramService) LatestPosts(ctx context.Context, username string) (*InstagramLatestPosts, error)
LatestPosts is GET /instagram/profile/{username}/timeline/latest — the first page of posts.
func (*InstagramService) Media ¶
func (s *InstagramService) Media(ctx context.Context, shortcode string) (*InstagramMediaDetail, error)
Media is GET /instagram/media/{shortcode} — shortcode from instagram.com/p/{shortcode}/.
func (*InstagramService) MediaByID ¶
func (s *InstagramService) MediaByID(ctx context.Context, username, mediaID string) (*InstagramMediaDetail, error)
MediaByID is GET /instagram/profile/{username}/media/{mediaId}.
func (*InstagramService) Posts ¶
func (s *InstagramService) Posts(ctx context.Context, username string, p *InstagramPostsParams) (*Page[InstagramMedia, InstagramTimelinePage], error)
Posts is GET /instagram/profile/{username}/timeline — full history, cursor-paginated; Count 1-50 (default 12).
func (*InstagramService) Profile ¶
func (s *InstagramService) Profile(ctx context.Context, username string) (*InstagramProfile, error)
Profile is GET /instagram/profile/{username} — username without @.
func (*InstagramService) Reel ¶
func (s *InstagramService) Reel(ctx context.Context, shortcode string) (*InstagramReel, error)
Reel is GET /instagram/reels/{shortcode}.
func (*InstagramService) ShortcodeToID ¶
func (s *InstagramService) ShortcodeToID(ctx context.Context, shortcode string) (*InstagramShortcodeID, error)
ShortcodeToID is GET /instagram/media/{shortcode}/id.
type InstagramShortcodeID ¶
type InstagramShortcodeID struct {
Shortcode string `json:"shortcode"`
MediaID string `json:"media_id"`
}
InstagramShortcodeID is GET /instagram/media/{shortcode}/id and /instagram/media/id/{mediaId}.
type InstagramTimelinePage ¶
type InstagramTimelinePage struct {
Medias []InstagramMedia `json:"medias"`
HasMore bool `json:"has_more"`
NextCursor *string `json:"next_cursor,omitempty"`
}
InstagramTimelinePage is GET /instagram/profile/{username}/timeline.
type LinktreeLink ¶
type LinktreeLink struct {
ID string `json:"id"`
Title string `json:"title"`
URL string `json:"url"`
Type string `json:"type"`
}
LinktreeLink is one link in a Linktree profile.
type LinktreeProfile ¶
type LinktreeProfile struct {
Username string `json:"username"`
Title string `json:"title"`
Description string `json:"description"`
Avatar string `json:"avatar"`
IsVerified bool `json:"is_verified"`
URL string `json:"url"`
Links []LinktreeLink `json:"links"`
}
LinktreeProfile is GET /linktree/profiles/{handle}.
type LinktreeService ¶
type LinktreeService struct {
// contains filtered or unexported fields
}
LinktreeService groups the Linktree endpoints.
func (*LinktreeService) Profile ¶
func (s *LinktreeService) Profile(ctx context.Context, handle string) (*LinktreeProfile, error)
Profile is GET /linktree/profiles/{handle}.
type Option ¶
type Option func(*config)
Option configures a Client.
func WithAPIKey ¶
WithAPIKey sets the API key (sinac_…). Defaults to the SCRAPINGISNOTACRIME_API_KEY environment variable.
func WithBaseURL ¶
WithBaseURL overrides the API base URL. It must be the final HTTPS URL: redirects are not followed.
func WithHTTPClient ¶
WithHTTPClient sets the *http.Client used for requests (proxies, tests). The client is never modified.
func WithMaxRetries ¶
WithMaxRetries sets the extra attempts for 429, 502 and network errors. Defaults to 2; 0 disables retries.
func WithTimeout ¶
WithTimeout sets the per-attempt timeout (connect, headers and body). Defaults to 30 s.
type Page ¶
type Page[T, R any] struct { Items []T HasMore bool NextCursor string NextPage int Data R // contains filtered or unexported fields }
Page is one page of results. Data is the full page object; Items, HasMore, NextCursor ("" = none) and NextPage (0 = none) are read from it. HasMore is true exactly when Next will fetch another page.
func (*Page[T, R]) All ¶
All yields every item from this page onward, fetching later pages lazily (each page is one billed request). Breaking out of the loop stops fetching. A fetch error is yielded once, with the zero item, and ends the iteration.
Example ¶
package main
import (
"context"
"fmt"
"log"
sinac "github.com/ScrapingIsNotACrime/sdk-go"
)
func main() {
client, err := sinac.NewClient() // reads SCRAPINGISNOTACRIME_API_KEY
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
page, err := client.GitHub.Followers(ctx, "torvalds", &sinac.GitHubListParams{Limit: 100})
if err != nil {
log.Fatal(err)
}
// Each page fetched is one billed request, so stop at a bound.
n := 0
for user, err := range page.All(ctx) {
if err != nil {
log.Fatal(err)
}
fmt.Println(user.Username)
if n++; n >= 250 {
break
}
}
}
Output:
type TikTokProfile ¶
type TikTokProfile struct {
ID string `json:"id"`
Username string `json:"username"`
Nickname string `json:"nickname"`
Bio string `json:"bio"`
BioLink string `json:"bio_link"`
Avatar string `json:"avatar"`
SecUID string `json:"sec_uid"`
Followers int64 `json:"followers"`
Following int64 `json:"following"`
Hearts int64 `json:"hearts"`
Videos int64 `json:"videos"`
IsPrivate bool `json:"is_private"`
IsVerified bool `json:"is_verified"`
}
TikTokProfile is GET /tiktok/profile/{username}.
type TikTokService ¶
type TikTokService struct {
// contains filtered or unexported fields
}
TikTokService groups the TikTok endpoints.
func (*TikTokService) Profile ¶
func (s *TikTokService) Profile(ctx context.Context, username string) (*TikTokProfile, error)
Profile is GET /tiktok/profile/{username}.
func (*TikTokService) Video ¶
func (s *TikTokService) Video(ctx context.Context, videoID string) (*TikTokVideo, error)
Video is GET /tiktok/video/{videoId}.
type TikTokVideo ¶
TikTokVideo is GET /tiktok/video/{videoId}. No documented example yet; Extra holds every other key.
func (TikTokVideo) MarshalJSON ¶
func (v TikTokVideo) MarshalJSON() ([]byte, error)
MarshalJSON re-encodes Extra plus id (when ID is set), so round-tripping through the SDK never loses data.
func (*TikTokVideo) UnmarshalJSON ¶
func (v *TikTokVideo) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes id into ID only when it is a JSON string; any other shape (number, null, ...) leaves ID nil and keeps the raw value in Extra, alongside every other key, so no data is ever dropped.
type TwitchBroadcast ¶
TwitchBroadcast is a channel's most recent broadcast.
type TwitchProfile ¶
type TwitchProfile struct {
ID string `json:"id"`
Login string `json:"login"`
DisplayName string `json:"display_name"`
Description string `json:"description"`
Avatar string `json:"avatar"`
Followers int64 `json:"followers"`
IsPartner bool `json:"is_partner"`
IsAffiliate bool `json:"is_affiliate"`
CreatedAt string `json:"created_at"`
IsLive bool `json:"is_live"`
// Current viewer count while live; null whenever is_live is false.
LiveViewers *int64 `json:"live_viewers,omitempty"`
// Null when the channel has never broadcast (or the info is unavailable).
LastBroadcast *TwitchBroadcast `json:"last_broadcast,omitempty"`
URL string `json:"url"`
}
TwitchProfile is GET /twitch/profiles/{handle}.
type TwitchService ¶
type TwitchService struct {
// contains filtered or unexported fields
}
TwitchService groups the Twitch endpoints.
func (*TwitchService) Profile ¶
func (s *TwitchService) Profile(ctx context.Context, handle string) (*TwitchProfile, error)
Profile is GET /twitch/profiles/{handle}.
func (*TwitchService) Videos ¶
func (s *TwitchService) Videos(ctx context.Context, handle string, p *TwitchVideosParams) (*TwitchVideos, error)
Videos is GET /twitch/profiles/{handle}/videos — limit 1-100, default 20.
type TwitchVideo ¶
type TwitchVideo struct {
ID string `json:"id"`
Title string `json:"title"`
DurationSeconds int64 `json:"duration_seconds"`
Views int64 `json:"views"`
PublishedAt string `json:"published_at"`
Thumbnail string `json:"thumbnail"`
URL string `json:"url"`
}
TwitchVideo is one video in a channel's published videos list.
type TwitchVideos ¶
type TwitchVideos struct {
Videos []TwitchVideo `json:"videos"`
Count int64 `json:"count"`
}
TwitchVideos is GET /twitch/profiles/{handle}/videos.
type TwitchVideosParams ¶
type TwitchVideosParams struct {
Limit int
}
TwitchVideosParams: Limit 1-100 (default 20).
type YouTubeChannel ¶
type YouTubeChannel struct {
Title string `json:"title"`
Description string `json:"description"`
ExternalID string `json:"externalId"`
Avatar string `json:"avatar"`
}
YouTubeChannel is the channel block in a channel-videos response.
type YouTubeChannelVideos ¶
type YouTubeChannelVideos struct {
Channel YouTubeChannel `json:"channel"`
Videos []YouTubeVideo `json:"videos"`
}
YouTubeChannelVideos is GET /youtube/channel/{handle}/videos.
type YouTubeService ¶
type YouTubeService struct {
// contains filtered or unexported fields
}
YouTubeService groups the YouTube endpoints.
func (*YouTubeService) Videos ¶
func (s *YouTubeService) Videos(ctx context.Context, handle string) (*YouTubeChannelVideos, error)
Videos is GET /youtube/channel/{handle}/videos.
Source Files
¶
- appstore.go
- bluesky.go
- client.go
- config.go
- doc.go
- errors.go
- github.go
- hackernews.go
- http.go
- instagram.go
- linktree.go
- pagination.go
- retry.go
- routes.go
- tiktok.go
- twitch.go
- types_appstore.go
- types_bluesky.go
- types_github.go
- types_hackernews.go
- types_instagram.go
- types_linktree.go
- types_tiktok.go
- types_twitch.go
- types_youtube.go
- version.go
- youtube.go