Horizon Ventures

Confluence CQL cheat sheet: queries you can copy

CQL is the query language behind Confluence search. Below are the queries people actually need, each one run against a live Confluence Cloud site before it went on this page, plus the few traps that quietly return the wrong pages.

Short answer. A CQL query is field operator value, joined with AND, OR and NOT, optionally followed by ORDER BY. Pages nobody touched in six months: type = page AND lastmodified < now("-26w"). Pages with two labels at once: label = "policy" AND label = "hr", not label IN (...), which means "any of". Your starred pages: favourite = currentUser().

Where to run it

Atlassian documents CQL as part of the Confluence REST API (Advanced searching using CQL). The quickest way to try a query, with your own permissions, is to open this address in a browser where you are logged in to Confluence, with your query at the end:

https://your-site.atlassian.net/wiki/rest/api/content/search?cql=type = page AND space = DEV

The browser fills in the encoding. You get JSON: titles, IDs and links in results, the total in totalSize. Scripts and apps use the same endpoint, which is why a query that works here works there too.

The building blocks

FieldWhat it matchesExample
typepage, blogpost, comment, attachment, whiteboard, database, foldertype IN (page, blogpost)
spaceSpace keyspace = DEV
titleTitle, exact or containstitle ~ "policy"
textWords anywhere in the contenttext ~ "vacation policy"
labelLabelslabel = "onboarding"
created, lastmodifiedDates, with functionslastmodified < now("-180d")
creator, contributorWho created or editedcontributor = currentUser()
favourite, watcher, mentionStarred by, watched by, mentioning a usermention = currentUser()
parent, ancestorDirect children, whole tree below a pageancestor = 123456
macroPages using a macromacro = "drawio"
pageStatusThe status lozenge on a pagepageStatus = "Verified"

Operators: =, !=, <, >, <=, >= (dates), IN, NOT IN, and ~, !~ (contains, for title and text). Date functions: now("-4w"), startOfDay(), startOfWeek("-1w"), startOfMonth(), startOfYear() and their endOf pairs. User functions: currentUser().

Queries for real tasks

Stale content

type = page AND lastmodified < now("-26w") ORDER BY lastmodified ASC
type = page AND space = DEV AND lastmodified < now("-180d")
type = page AND lastmodified < startOfYear()
type = page AND lastmodified < now("-180d") AND NOT label = "archived"

Oldest first is the useful order: the top of the list is where the forgotten pages are. More on what to do with them in how to find the Confluence pages nobody maintains.

Labels

label = "policy" AND label = "hr"          (both labels)
label IN ("policy", "hr")                  (either label)
type = page AND label NOT IN ("archived")

You and your colleagues

favourite = currentUser()                  (your starred pages)
creator = currentUser() AND type = page    (pages you created)
contributor = currentUser() ORDER BY lastmodified DESC
mention = currentUser()                    (pages that @mention you)
watcher = currentUser()

For another person, use their account ID instead of currentUser(): names do not work in Confluence Cloud, which only matches users by account ID.

A section of the tree

parent = 123456      (direct children only)
ancestor = 123456    (everything below, at any depth)

The number is the page ID, the digits in the page address after /pages/.

By content

title ~ "policy" AND type = page
text ~ "vacation policy"
macro = "drawio"                 (pages with a draw.io diagram)
type = attachment AND title ~ "docx"
pageStatus = "Rough draft"

Recent activity

created >= startOfWeek("-1w") AND type = blogpost
type IN (page, blogpost) AND space IN (DEV, OPS) ORDER BY created DESC

Traps that return the wrong pages

The arithmetic

Writing a query takes a minute once you know the fields. The cost is elsewhere: CQL results live in a JSON response or a script, not on a page your colleagues read. A monthly "pages not updated in six months" list for five teams means someone runs five queries, turns JSON into something readable and posts it, every month. That is roughly an hour a month for one person, and it stops the month that person is busy.

If you only need an answer for yourself once, the browser address above is free and enough.

When the list should live on a page

Disclosure: I build Smart Search for Confluence. It builds the CQL for you from simple settings (space, labels, words, "not updated for N days") and shows the result as a live list on a Confluence page, so readers see it without running anything. Several labels mean all of them, as most people expect. It runs inside Atlassian's infrastructure and is free for teams up to ten people.

Frequently asked

How do I find pages not updated in 6 months?

type = page AND lastmodified < now("-26w") ORDER BY lastmodified ASC. Offsets like -180d or -6M work too; lowercase -6m is six minutes.

How do I find pages with two labels at once?

One condition per label, joined with AND. label IN returns pages with any of them.

How do I list my starred pages?

favourite = currentUser(). It only ever shows your own starred pages, never someone else's.

What is the difference between ancestor and parent?

parent gives direct children, ancestor the whole tree below a page.

Can I search by a person's name?

Not in Confluence Cloud: user fields take account IDs. currentUser() covers the common case of searching for yourself.

Related: how to list Confluence pages on a page without writing CQL, finding pages nobody maintains, and what to use now that CQL Search is ending.