Goquery
A little like that j-thing, only in Go.
Install / Use
/learn @PuerkitoBio/GoqueryREADME
goquery - a little like that j-thing, only in Go
goquery brings a syntax and a set of features similar to [jQuery][] to the [Go language][go]. It is based on Go's [net/html package][html] and the CSS Selector library [cascadia][]. Since the net/html parser returns nodes, and not a full-featured DOM tree, jQuery's stateful manipulation functions (like height(), css(), detach()) have been left off.
Also, because the net/html parser requires UTF-8 encoding, so does goquery: it is the caller's responsibility to ensure that the source document provides UTF-8 encoded HTML. See the [wiki][] for various options to do this.
Syntax-wise, it is as close as possible to jQuery, with the same function names when possible, and that warm and fuzzy chainable interface. jQuery being the ultra-popular library that it is, I felt that writing a similar HTML-manipulating library was better to follow its API than to start anew (in the same spirit as Go's fmt package), even though some of its methods are less than intuitive (looking at you, [index()][index]...).
Table of Contents
Installation
Required Go version:
- Starting with version
v1.12.0of goquery, Go 1.25+ is required due to its dependencies. - Starting with version
v1.11.0of goquery, Go 1.24+ is required due to its dependencies. - Starting with version
v1.10.0of goquery, Go 1.23+ is required due to the use of function-based iterators. - For
v1.9.0of goquery, Go 1.18+ is required due to the use of generics. - For previous goquery versions, a Go version of 1.1+ was required because of the
net/htmldependency.
Ongoing goquery development is tested on the latest 2 versions of Go.
$ go get github.com/PuerkitoBio/goquery
(optional) To run unit tests:
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test
(optional) To run benchmarks (warning: it runs for a few minutes):
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test -bench=".*"
Changelog
Note that goquery's API is now stable, and will not break.
- 2026-03-15 (v1.12.0) : Update
go.moddependencies, add go1.26 to the test matrix, goquery now requires Go version 1.25+. - 2025-11-16 (v1.11.0) : Update
go.moddependencies, add go1.25 to the test matrix, goquery now requires Go version 1.24+. - 2025-04-11 (v1.10.3) : Update
go.moddependencies, small optimization (thanks @myxzlpltk). - 2025-02-13 (v1.10.2) : Update
go.moddependencies, add go1.24 to the test matrix. - 2024-12-26 (v1.10.1) : Update
go.moddependencies. - 2024-09-06 (v1.10.0) : Add
EachIterwhich provides an iterator that can be used infor..rangeloops on the*Selectionobject. goquery now requires Go version 1.23+ (thanks @amikai). - 2024-09-06 (v1.9.3) : Update
go.moddependencies. - 2024-04-29 (v1.9.2) : Update
go.moddependencies. - 2024-02-29 (v1.9.1) : Improve allocation and performance of the
Mapfunction andSelection.Mapmethod, better document the cascadia differences (thanks @jwilsson). - 2024-02-22 (v1.9.0) : Add a generic
Mapfunction, goquery now requires Go version 1.18+ (thanks @Fesaa). - 2023-02-18 (v1.8.1) : Update
go.moddependencies, update CI workflow. - 2021-10-25 (v1.8.0) : Add
Renderfunction to render aSelectionto anio.Writer(thanks @anthonygedeon). - 2021-07-11 (v1.7.1) : Update go.mod dependencies and add dependabot config (thanks @jauderho).
- 2021-06-14 (v1.7.0) : Add
SingleandSingleMatcherfunctions to optimize first-match selection (thanks @gdollardollar). - 2021-01-11 (v1.6.1) : Fix panic when calling
{Prepend,Append,Set}Htmlon aSelectionthat contains non-Element nodes. - 2020-10-08 (v1.6.0) : Parse html in context of the container node for all functions that deal with html strings (
AfterHtml,AppendHtml, etc.). Thanks to [@thiemok][thiemok] and [@davidjwilkins][djw] for their work on this. - 2020-02-04 (v1.5.1) : Update module dependencies.
- 2018-11-15 (v1.5.0) : Go module support (thanks @Zaba505).
- 2018-06-07 (v1.4.1) : Add
NewDocumentFromReaderexamples. - 2018-03-24 (v1.4.0) : Deprecate
NewDocument(url)andNewDocumentFromResponse(response). - 2018-01-28 (v1.3.0) : Add
ToEndconstant toSliceuntil the end of the selection (thanks to @davidjwilkins for raising the issue). - 2018-01-11 (v1.2.0) : Add
AddBack*and deprecateAndSelf(thanks to @davidjwilkins). - 2017-02-12 (v1.1.0) : Add
SetHtmlandSetText(thanks to @glebtv). - 2016-12-29 (v1.0.2) : Optimize allocations for
Selection.Text(thanks to @radovskyb). - 2016-08-28 (v1.0.1) : Optimize performance for large documents.
- 2016-07-27 (v1.0.0) : Tag version 1.0.0.
- 2016-06-15 : Invalid selector strings internally compile to a
Matcherimplementation that never matches any node (instead of a panic). So for example,doc.Find("~")returns an empty*Selectionobject. - 2016-02-02 : Add
NodeNameutility function similar to the DOM'snodeNameproperty. It returns the tag name of the first element in a selection, and other relevant values of non-element nodes (see [doc][] for details). AddOuterHtmlutility function similar to the DOM'souterHTMLproperty (namedOuterHtmlin small caps for consistency with the existingHtmlmethod on theSelection). - 2015-04-20 : Add
AttrOrhelper method to return the attribute's value or a default value if absent. Thanks to [piotrkowalczuk][piotr]. - 2015-02-04 : Add more manipulation functions - Prepend* - thanks again to [Andrew Stone][thatguystone].
- 2014-11-28 : Add more manipulation functions - ReplaceWith*, Wrap* and Unwrap - thanks again to [Andrew Stone][thatguystone].
- 2014-11-07 : Add manipulation functions (thanks to [Andrew Stone][thatguystone]) and
*Matcherfunctions, that receive compiled cascadia selectors instead of selector strings, thus avoiding potential panics thrown by goquery viacascadia.MustCompilecalls. This results in better performance (selectors can be compiled once and reused) and more idiomatic error handling (you can handle cascadia's compilation errors, instead of recovering from panics, which had been bugging me for a long time). Note that the actual type expected is aMatcherinterface, thatcascadia.Selectorimplements. Other matcher implementations could be used. - 2014-11-06 : Change import paths of net/html to golang.org/x/net/html (see https://groups.google.com/forum/#!topic/golang-nuts/eD8dh3T9yyA). Make sure to update your code to use the new import path too when you call goquery with
html.Nodes. - v0.3.2 : Add
NewDocumentFromReader()(thanks jweir) which allows creating a goquery document from an io.Reader. - v0.3.1 : Add
NewDocumentFromResponse()(thanks assassingj) which allows creating a goquery document from an http response. - v0.3.0 : Add
EachWithBreak()which allows to break out of anEach()loop by returning false. This function was added instead of changing the existingEach()to avoid breaking compatibility. - v0.2.1 : Make go-getable, now that [go.net/html is Go1.0-compatible][gonet] (thanks to @matrixik for pointing this out).
- v0.2.0 : Add support for negative indices in Slice(). BREAKING CHANGE
Document.Rootis removed,Documentis now aSelectionitself (a selection of one, the root element, just likeDocument.Rootwas before). Add jQuery's Closest() method. - v0.1.1 : Add benchmarks to use as baseline for refactorings, refactor Next...() and Prev...() methods to use the new html package's linked list features (Next/PrevSibling, FirstChild). Good performance boost (40+% in some cases).
- v0.1.0 : Initial release.
API
goquery exposes two structs, Document and Selection, and the Matcher interface. Unlike jQuery, which is loaded as part of a DOM document, and thus acts on its containing document, goquery doesn't know which HTML document to act upon. So it needs to be told, and that's what the Document type is for. It holds the root document node as the initial Selection value to manipulate.
jQuery often has many variants for the same function (no argument, a selector string argument, a jQuery object argument, a DOM element argument, ...). Instead of exposing the same features in goquery as a single method with variadic empty interface arguments, statically-typed signatures are used following this naming convention:
- When the jQuery equivalent can be called with no argument, it has the same name as jQuery for the no argument signature (e.g.:
Prev()), and the version with a selector string argument is calledXxxFiltered()(e.g.:PrevFiltered()) - When the jQuery equivalent requires one argument, the same name as jQuery is used for the selector string version (e.g.:
Is()) - The signatures accepting a jQuery object as argument are defined in goquery as
XxxSelection()and take a*Selectionobject as argument (e.g.: `FilterSelection(
Related Skills
node-connect
345.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
106.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
345.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
345.9kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
