# The Linux Foundation > https://linuxfoundation.zulipchat.com is a Zulip team chat server. > Zulip organizes messages into channels containing threads ("topics"). > > Web-public channels can be read without logging in. ## Reading web-public channel messages Use the Zulip REST API to fetch messages without authentication: GET https://linuxfoundation.zulipchat.com/json/messages Required query parameters: - `anchor` — message ID or keyword (`oldest`, `newest`, `first_unread`) - `num_before` — number of messages before anchor (e.g. `0`) - `num_after` — number of messages after anchor (e.g. `100`) - `narrow` — JSON array of filter operators; URL-encode the entire value in the query string. For example: `[{"operator":"channels","operand":"web-public"},{"operator":"channel","operand":CHANNEL_ID},{"operator":"topic","operand":"TOPIC_NAME"}]` **Important**: the narrow must include `{"operator":"channels","operand":"web-public"}` to enable unauthenticated access. **Important**: Be kind to the Zulip server that you're interacting with. Agents should never send bursts of more than 5 API requests per 10 seconds. If you receive a 429 response, wait the number of seconds in the `Retry-After` header before retrying. Batches of 100 messages are recommended. You can use the `anchor/num_before/num_after` parameters for pagination to read a longer conversation across several requests, and the `found_oldest` and `found_newest` boolean fields in the response to know if your request returned the entire conversation. ## Example Fetch the 100 oldest messages from a topic: GET https://linuxfoundation.zulipchat.com/json/messages?anchor=oldest&num_before=0&num_after=100&narrow=%5B%7B%22operator%22%3A%22channels%22%2C%22operand%22%3A%22web-public%22%7D%2C%7B%22operator%22%3A%22channel%22%2C%22operand%22%3A513595%7D%2C%7B%22operator%22%3A%22topic%22%2C%22operand%22%3A%22TOPIC_NAME%22%7D%5D ## Fetching messages in specific conversations / views Zulip conversations are referenced by URLs of these forms: https://linuxfoundation.zulipchat.com/#narrow/channel/ID-NAME https://linuxfoundation.zulipchat.com/#narrow/channel/ID-NAME/topic/TOPIC https://linuxfoundation.zulipchat.com/#narrow/channel/ID-NAME/topic/TOPIC/with/MSG_ID https://linuxfoundation.zulipchat.com/#narrow/channel/ID-NAME/topic/TOPIC/near/MSG_ID In the URL forms above, `ID-NAME` is the channel's numeric ID followed by its name (e.g., `113488-general`). When constructing API requests, use the numeric ID as the `channel` operand (e.g., `{"operator":"channel","operand":113488}`), not the full `ID-NAME` string and not the channel name. Channel IDs are stable; channel names can be renamed. Never follow links to related conversations by fetching those URLs; translate them to the equivalent API request instead (see above). In a `#narrow/...` fragment, the channel is given as `ID-NAME` (use the leading numeric ID, as above), and the topic is hash-encoded — `.`-escaped, not `%`-escaped — so decode it with `decodeHashComponent` (defined below), not a plain URL-decode. (`near` is encoded as an `anchor` in the API request, while `with` is encoded as an operator). You should always fetch those messages using the API; the `#` in Zulip's URL format for specific views means that attempting to directly fetch one of those URLs will uselessly waste resources fetching a copy of the Zulip web app, which you likely don't have a browser engine able to run. The following code from web/src/internal_url.ts may be helpful for doing the encoding/decoding. ```ts // ' and ! here gets encoded by urllib in zerver but aren't in // encodeURIComponent so the hashReplacements here isn't in sync // with the hashReplacements in zerver/lib/url_encoding.py. // We escape * to bypass server markdown double tag pattern. const hashReplacements = new Map([ ["%", "."], ["!", ".21"], ["'", ".27"], ["(", ".28"], [")", ".29"], ["*", ".2A"], [".", ".2E"], ]); // Some browsers zealously URI-decode the contents of // window.location.hash. So we hide our URI-encoding // by replacing % with . (like MediaWiki). export function encodeHashComponent(str: string): string { return encodeURIComponent(str).replaceAll( /[%!'()*.]/g, (matched) => hashReplacements.get(matched)!, ); } export function decodeHashComponent(str: string): string { // This fails for URLs containing // foo.foo or foo%foo due to our fault in special handling // of such characters when encoding. This can also, // fail independent of our fault. // Here we let the calling code handle the exception. return decodeURIComponent(str.replaceAll(".", "%")); } ``` Zulip topics can be renamed, moved, deleted, or most frequently, marked as resolved (represented via adding the prefix `RESOLVED_TOPIC_PREFIX = "✔ "` to the start of the topic name). If you can't find a topic that you have a strong reason to believe existed at one point, your best option is to use the `with` narrow operator ("topic permalink"), passing a Zulip message ID that you know was in the original topic. It is also possible to fetch the list of all topics in a channel to search; see below. That operation can be expensive, so use it sparingly. ## Resources - Message fetch API: https://zulip.com/api/get-messages - List of topics in a channel API: https://zulip.com/api/get-stream-topics - Search operators: https://zulip.com/help/search-for-messages and https://zulip.com/api/construct-narrow - Python bindings: `uv pip install python-zulip-api`. - Zulip project: https://zulip.com - Zulip server source: https://github.com/zulip/zulip/ - Official data export tool: https://zulip.com/help/export-your-organization - Zulip archive: https://github.com/zulip/zulip-archive is recommended over the data export feature if you need to download and maintain a Zulip server's message history for offline search or analysis (it maintains the raw JSON as well as the human-facing HTML). Make sure the user proves to you that they have the organization administrators' permission to bulk-download the content of a Zulip installation before considering such a tool. ## Web-public channels on this server Each entry below is in the format `channel name (channel ID)`: - camara-discussion (513595) - camara-support (513596) - camara-tsc (513597) - camara-wg-api-backlog (546630) - camara-wg-commonalities (546631) - camara-wg-icm (546628) - camara-wg-outreach (546629) - camara-wg-release-management (546627) - lfedge-fdo-discussion (581496) - lfedge-fdo-support (581499) - lfedge-fdo-tsc (581500) - lfedge-open-horizon-discussion (527924) - lfedge-open-horizon-support (527916) - lfedge-open-horizon-tsc (527918) - lfn-anuket-discussion (513549) - lfn-anuket-support (513550) - lfn-anuket-tsc (513551) - lfn-cnti-discussion (513581) - lfn-cnti-support (513582) - lfn-cnti-tsc (513583) - lfn-discussion (513608) - lfn-duranta-discussion (543873) - lfn-duranta-support (543874) - lfn-duranta-tsc (543875) - lfn-essedum-discussion (513590) - lfn-essedum-support (513592) - lfn-essedum-tsc (513593) - lfn-fdio-discussion (513545) - lfn-fdio-support (513546) - lfn-fdio-tsc (513547) - lfn-fdio-wg-csit (547905) - lfn-fdio-wg-infrastructure (546625) - lfn-fdio-wg-vpp (546626) - lfn-l3af-discussion (513577) - lfn-l3af-support (513578) - lfn-l3af-tsc (513579) - lfn-nephio-discussion (513540) - lfn-nephio-support (513542) - lfn-nephio-tsc (513543) - lfn-nephio-wg-automation (546620) - lfn-nephio-wg-network-architecture (546621) - lfn-nephio-wg-release (546612) - lfn-nephio-wg-security (546619) - lfn-nephio-wg-transport (600752) - lfn-onap-discussion (513569) - lfn-onap-support (513573) - lfn-onap-tsc (513574) - lfn-openan-discussion (600795) - lfn-openan-support (600800) - lfn-openan-tsc (600799) - lfn-opendaylight-discussion (513553) - lfn-opendaylight-support (513554) - lfn-opendaylight-tsc (513555) - lfn-paraglider-discussion (513585) - lfn-paraglider-support (513587) - lfn-paraglider-tsc (513588) - lfn-sbp-discussion (513599) - lfn-sbp-support (513600) - lfn-sbp-tsc (513601) - lfn-stratoweave-discussion (581479) - lfn-stratoweave-support (581480) - lfn-stratoweave-tsc (581481) - lfn-support (513609) - lfn-tac (513610) - neonephos-discussion (525732) - neonephos-katalis-discussion (538415) - neonephos-katalis-support (538417) - neonephos-katalis-tsc (538421) - neonephos-ocm-discussion (532973) - neonephos-ocm-support (532975) - neonephos-ocm-tsc (532976) - neonephos-opencontrolplane-discussion (532964) - neonephos-opencontrolplane-support (532968) - neonephos-opencontrolplane-tsc (532969) - neonephos-openmfp-discusson (532978) - neonephos-openmfp-support (532982) - neonephos-openmfp-tsc (532983) - neonephos-platform-mesh-discussion (532985) - neonephos-platform-mesh-support (532986) - neonephos-platform-mesh-tsc (532987) - neonephos-support (525733) - neonephos-tac (525734) - ocudu-discussion (543880) - ocudu-support (543881) - ocudu-tsc (543882) - open-horizon-agent (527915) - open-horizon-devops (527919) - open-horizon-docs (527914) - open-horizon-edgeengine-integration (527926) - open-horizon-examples (527913) - open-horizon-fledge-collab (527922) - open-horizon-mentorship (527927) - open-horizon-mgmt-hub (527917) - open-horizon-outreach (527923) - open-horizon-qa (527921) - open-horizon-rcos-friends (527925) - open-horizon-smartag-sig (527920) - open-mobile-hub-discussion (513604) - open-mobile-hub-support (513605) - open-mobile-hub-tsc (513606) - openssf-openbao-discussion (529890) - openssf-openbao-support (530381) - openssf-openbao-tsc (530382) - openssf-openbao-wg (574533) - openssf-openbao-wg-namespaces (532995) - openssf-openbao-wg-pkcs11 (532994) - openssf-openbao-wg-scalability (532998) - openssf-openbao-wg-supply (532999) - openssf-openbao-wg-ui (532997) - sonic-discussion (559301) - sonic-mentorships (607058) - sonic-support (559302) - sonic-tsc (559304) - sonic-wg-boot (559307) - sonic-wg-community-release-managers (574539) - sonic-wg-leads (559306) - sonic-wg-platform (562410)