douyin

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 14, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package douyin is the library behind the douyin command line: the HTTP client, the open hot-search billboard, the signed web API calls, and the typed data models for Douyin (抖音).

Two hosts feed the records. The open plane reads www.iesdouyin.com/web/api/v2/hotsearch/billboard/* and needs no signing. The API plane calls www.douyin.com/aweme/v1/web/* with an X-Bogus signature and an msToken, the way the web client signs them. The API plane sits behind an anti-bot wall that scores the caller; when it wins it serves an empty body or a __ac challenge stub, so the client returns ErrWalled and the command layer reports it honestly instead of a silent empty result.

Index

Constants

View Source
const DefaultUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"

DefaultUserAgent is a current desktop Chrome string. An honest, real User-Agent is both polite and the thing most likely to keep a session unblocked, because the Douyin API scores non-browser callers.

View Source
const Host = "https://www.douyin.com"

Host is the web origin the signed API targets.

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound means the call parsed but carried no record for the request, for example an aweme id that does not exist or a private profile with no items.

View Source
var ErrWalled = errors.New("douyin served an anti-bot challenge (this surface needs a residential session)")

ErrWalled means the anti-bot wall served a challenge or a signed call came back empty. The surface needs a residential session (a China IP and a warm __ac cookie).

Functions

func BaseIdentity added in v0.1.1

func BaseIdentity() kit.Identity

BaseIdentity is the help and version identity shared by the standalone binary and any host that links the package.

func Defaults added in v0.1.1

func Defaults(c *kit.Config)

Defaults seeds the framework baseline from the douyin defaults, so an unset --rate/--retries/--timeout keeps the library's own pacing.

func IsSecUID added in v0.1.1

func IsSecUID(s string) bool

IsSecUID reports whether s looks like a Douyin sec_uid rather than a video id. A sec_uid is a long opaque token starting with "MS4wLjAB".

func MapErr added in v0.1.1

func MapErr(err error) error

MapErr converts a library error into the kit error kind that carries the right exit code, so a host renders the same walled and not-found outcomes the standalone binary does. An anti-bot challenge is exit 4 (needs a residential session), a missing record is exit 6.

func ParseSecUID added in v0.1.1

func ParseSecUID(in string) (string, error)

ParseSecUID pulls a sec_uid out of a /user/{sec_uid} url, or accepts a bare sec_uid token. A Douyin sec_uid is a long opaque string starting with "MS4wLjAB" and is not all digits.

func ParseVideoID added in v0.1.1

func ParseVideoID(in string) (string, error)

ParseVideoID pulls a numeric aweme id out of a /video/{id} or /note/{id} url, or accepts a bare numeric id.

func Register added in v0.1.1

func Register(app *kit.App)

Register is the convenience a host or the binary calls without naming the zero-value Domain.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to Douyin over HTTP.

func NewClient

func NewClient(cfg Config) *Client

NewClient builds a Client from cfg.

func (*Client) Comments added in v0.1.1

func (c *Client) Comments(ctx context.Context, videoID string, limit int) ([]Comment, error)

Comments pages the comment list under a video.

func (*Client) GetAPI added in v0.1.1

func (c *Client) GetAPI(ctx context.Context, path, rawQuery string) ([]byte, error)

GetAPI signs an /aweme/v1/web/{path} call, fetches it, and returns the JSON body. An empty body or an __ac challenge stub on a 200 is the wall gating the call, so it maps to ErrWalled.

func (*Client) GetHot added in v0.1.1

func (c *Client) GetHot(ctx context.Context, path, rawQuery string) ([]byte, error)

GetHot fetches an open billboard endpoint and returns its JSON body. It needs no signing. An empty body or an __ac challenge stub maps to ErrWalled.

func (*Client) Hot

func (c *Client) Hot(ctx context.Context, limit int) ([]Topic, error)

Hot fetches the realtime word billboard. It is open and needs no signing.

func (*Client) HotMusic added in v0.1.1

func (c *Client) HotMusic(ctx context.Context, limit int) ([]Topic, error)

HotMusic fetches the trending-music billboard. It is open and needs no signing.

func (*Client) HotStar added in v0.1.1

func (c *Client) HotStar(ctx context.Context, limit int) ([]Topic, error)

HotStar fetches the star billboard. It is open and needs no signing.

func (*Client) HotVideo added in v0.1.1

func (c *Client) HotVideo(ctx context.Context, limit int) ([]Topic, error)

HotVideo fetches the trending-video billboard. It is open and needs no signing. The entries are awemes, which collapse to thin Topic rows.

func (*Client) Posts added in v0.1.1

func (c *Client) Posts(ctx context.Context, secUID string, limit int, cursor string) ([]Video, error)

Posts pages a user's videos through aweme/post. It returns up to limit videos (0 means one page).

func (*Client) Raw added in v0.1.1

func (c *Client) Raw(ctx context.Context, url string) ([]byte, error)

Raw fetches an arbitrary url with the open browser headers and returns the body untouched. It is the escape hatch behind `douyin raw`: it does no signing and no parsing, so it works for the open billboards and shows exactly what the wall returns on a signed surface. An empty body or an __ac challenge stub maps to ErrWalled.

func (*Client) Search added in v0.1.1

func (c *Client) Search(ctx context.Context, keyword string, limit int) ([]SearchHit, error)

Search runs a general search and returns thin, normalized hits.

func (*Client) UserAgent added in v0.1.1

func (c *Client) UserAgent() string

UserAgent returns the configured User-Agent.

func (*Client) UserBySecUID added in v0.1.1

func (c *Client) UserBySecUID(ctx context.Context, secUID string) (User, error)

UserBySecUID fetches one profile record through the signed web API.

func (*Client) VideoByID added in v0.1.1

func (c *Client) VideoByID(ctx context.Context, id string) (Video, error)

VideoByID fetches one aweme detail record through the signed web API.

type Comment added in v0.1.1

type Comment struct {
	ID         string `json:"id" kit:"id"`
	VideoID    string `json:"video_id"`
	Text       string `json:"text" kit:"body" table:"text,truncate"`
	Author     string `json:"author"`
	AuthorID   string `json:"author_id"`
	AuthorNick string `json:"author_nick"`
	CreateTime int64  `json:"create_time"`
	LikeCount  int64  `json:"like_count"`
	ReplyCount int64  `json:"reply_count"`
	ParentID   string `json:"parent_id"`
	URL        string `json:"url"`
}

Comment is one comment under a video, with its parent id for replies.

type Config

type Config struct {
	UserAgent string
	Rate      time.Duration
	Timeout   time.Duration
	Retries   int
}

Config holds the tunable client settings.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns polite defaults: a 600ms gap between requests, a 30s timeout, and five retries on transient errors.

type Domain added in v0.1.1

type Domain struct{}

Domain is the Douyin driver. It carries no state; the per-run client is built by the factory Register hands kit.

func (Domain) Classify added in v0.1.1

func (Domain) Classify(input string) (uriType, id string, err error)

Classify turns any accepted input into the canonical (type, id), so `ant resolve` and `ant url` need no network. A /video/ link or a bare aweme id maps to a video; a /user/ link or a bare sec_uid maps to a user.

func (Domain) Info added in v0.1.1

func (Domain) Info() kit.DomainInfo

Info describes the scheme, the hostnames a pasted link is matched against, and the identity a host reuses for help and version.

func (Domain) Locate added in v0.1.1

func (Domain) Locate(uriType, id string) (string, error)

Locate is the inverse: the live https URL for a (type, id), built without a fetch.

func (Domain) Register added in v0.1.1

func (Domain) Register(app *kit.App)

Register installs the client factory and every Douyin operation onto app. It is the single point both surfaces go through: cli.NewApp calls it for the standalone binary, and a host calls Domain.Register for douyin:// URIs.

type SearchHit added in v0.1.1

type SearchHit struct {
	Type   string `json:"type"`
	ID     string `json:"id" kit:"id"`
	Title  string `json:"title" table:"title,truncate"`
	Author string `json:"author"`
	URL    string `json:"url"`
}

SearchHit is a thin, normalized search result row.

type Session added in v0.1.1

type Session struct {
	Client *Client
	Quiet  bool
}

Session is the per-run client kit injects into every operation. It pairs the HTTP client with the resolved quiet flag, so an operation can pace its own stderr progress without reaching for a global.

func (*Session) Progressf added in v0.1.1

func (s *Session) Progressf(format string, args ...any)

Progressf prints a one-line progress note to stderr unless the run is quiet.

type Topic

type Topic struct {
	Rank     int    `json:"rank"`
	Word     string `json:"word" kit:"id" table:"word,truncate"`
	HotValue int64  `json:"hot_value"`
	Label    string `json:"label"`
	Tab      string `json:"tab"`
	URL      string `json:"url"`
}

Topic is one hot-search billboard entry, ranked 1-based.

type User added in v0.1.1

type User struct {
	SecUID         string `json:"sec_uid" kit:"id"`
	UID            string `json:"uid"`
	Nickname       string `json:"nickname"`
	UniqueID       string `json:"unique_id"`
	Signature      string `json:"signature" kit:"body" table:"signature,truncate"`
	Verified       bool   `json:"verified"`
	Private        bool   `json:"private"`
	Region         string `json:"region"`
	FollowerCount  int64  `json:"follower_count"`
	FollowingCount int64  `json:"following_count"`
	TotalFavorited int64  `json:"total_favorited"`
	AwemeCount     int64  `json:"aweme_count"`
	FavoritingNum  int64  `json:"favoriting_count"`
	Avatar         string `json:"avatar"`
	URL            string `json:"url"`
}

User is a public profile, addressed by its sec_uid.

type Video added in v0.1.1

type Video struct {
	ID           string `json:"id" kit:"id"`
	Desc         string `json:"desc" kit:"body" table:"desc,truncate"`
	CreateTime   int64  `json:"create_time"`
	Author       string `json:"author"`
	AuthorSecUID string `json:"author_sec_uid"`
	AuthorNick   string `json:"author_nick"`
	MusicID      string `json:"music_id"`
	MusicTitle   string `json:"music_title" table:"music_title,truncate"`
	MusicAuthor  string `json:"music_author"`
	Duration     int64  `json:"duration"`
	Cover        string `json:"cover"`
	PlayAddr     string `json:"play_addr"`
	Width        int64  `json:"width"`
	Height       int64  `json:"height"`
	DiggCount    int64  `json:"digg_count"`
	ShareCount   int64  `json:"share_count"`
	CommentCount int64  `json:"comment_count"`
	PlayCount    int64  `json:"play_count"`
	CollectCount int64  `json:"collect_count"`
	URL          string `json:"url"`
}

Video is a single aweme with its author, music, and counters.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL