Skip to content
Said in Council

Open data

Download the record

Everything on this site, as files you can open in a spreadsheet or load into your own tools. They are rebuilt with the site every day; this copy is as of 4 November 2026. CSV files are UTF-8, comma-separated, with a header row; lists inside a cell are separated by "; ". Each JSON file carries the same notes as this page (source, AI labels, licence, columns) followed by its rows.

Two kinds of source, kept apart: the City's signed minutes (read in code, no AI) and AI drafts from the City's livestreams. Every AI-derived field is named as such in the notes, with the model; where a person checked or corrected something, a column says so. Check AI-drafted rows against the video link before you rely on them.

Licence. Our compilation (the selection, structure, transcripts, summaries and labels) is published underCC BY 4.0: reuse it freely, crediting "Said in Council" with a link to said-in-council.co.za. The City of Johannesburg's own documents and videos linked from these files remain the City's.

Council meetings (signed minutes)

From the minutes65 rows · 26 January 2023 to 20 March 2026

Each City of Johannesburg council meeting whose signed minutes this site has read: dates, the PDF, start times and how many votes and motions they record. Attendance, votes and motions join to it by minutes_id.

Source: The City of Johannesburg's signed council minutes (PDFs on joburg.org.za), read in code.

AI and checks: No AI. Everything is as printed in the minutes (blank where they don't say), except first_seen, the date this site first found the PDF online.

CSV 21 kBJSON 34 kB

Columns (14)
minutes_id
Id of the minutes (the PDF's file name); attendance, votes and motions use it
date
First day of the meeting
dates
All days, space-separated
meeting
Meeting title as printed
minutes_url
The signed minutes (PDF) on joburg.org.za
scheduled
Start time printed in the header (per day when the days differ)
commenced
Actual start, when the minutes record a late one
delay_reason
The reason given for the late start
present
Names listed present
on_leave
Names listed on leave
counted_votes
Counted votes printed
motions
Motions listed
scanned
true when read from a scanned image with OCR
first_seen
Date this site first found the minutes online

Attendance per councillor per meeting

From the minutes17 124 rows · 26 January 2023 to 20 March 2026

Who was present, on leave or absent without leave at each City of Johannesburg council meeting, one row per councillor per meeting, from the City's signed minutes. The JSON groups the rows by meeting.

Source: The City of Johannesburg's signed council minutes (PDFs on joburg.org.za), read in code.

AI and checks: No AI. Present, leave, late and left early are as printed in the minutes. "absent" is never printed: this site infers it (on council before and after the meeting, no name in the minutes that could be them, no party-wide leave), and never from scanned minutes.

CSV 1.9 MBJSON 2.7 MB

Columns (9)
date
First day of the meeting (YYYY-MM-DD)
minutes_id
The meeting; its title, PDF and dates are in the meetings dataset
councillor_id
This site's id; the councillor's page is /councillors/<id>/
name
Councillor's name (from the City's councillor list when matched, else as spelled in the minutes)
party
Party
status
present or leave (as printed), or absent (inferred by this site; see the AI note)
leave_reason
Reason for leave, as printed
late
Listed as arriving late (true/false)
left_early
Listed as leaving early (true/false)

The JSON has one row per meeting (minutes_id, date, meeting, minutes_url, scanned) with that meeting's rows in attendance.

Counted votes

From the minutes86 rows · 26 January 2023 to 20 March 2026

Every counted vote (for, against, abstain) printed in the City of Johannesburg's signed council minutes, with the parties recorded as dissenting.

Source: The City of Johannesburg's signed council minutes (PDFs on joburg.org.za), read in code.

AI and checks: No AI. Counts, outcome and dissent are as printed; outcome_from_count is true where the minutes print no outcome and this site took it from the count (more for than against).

CSV 35 kBJSON 50 kB

Columns (14)
date
First day of the meeting
minutes_id
The meeting (see the meetings dataset)
meeting
Meeting title as printed
item
Agenda item, motion or section number, as printed
title
Heading above the vote
for
Votes for
against
Votes against
abstain
Abstentions (blank when no abstain line is printed)
outcome
carried or defeated
outcome_from_count
true when no outcome is printed and it was read from the count
dissent
Parties recorded as dissenting, separated by "; "
page
PDF page of the count
minutes_url
The minutes PDF, opened at that page
scanned
true when read from a scanned image with OCR

Motions

From the minutes108 rows · 26 January 2023 to 26 February 2026

Every motion listed in the MOTIONS section of the City of Johannesburg's signed council minutes, with its proposer and outcome.

Source: The City of Johannesburg's signed council minutes (PDFs on joburg.org.za), read in code.

AI and checks: No AI. Everything is as printed; blank where the minutes don't say.

CSV 46 kBJSON 60 kB

Columns (11)
date
First day of the meeting
minutes_id
The meeting (see the meetings dataset)
meeting
Meeting title as printed
item
Agenda section number
number
Motion number, when numbered
title
Motion title
mover
The Proposer line as printed
outcome
adopted, rejected, withdrawn, deferred, referred or "not considered" (proposer absent); blank when not stated
page
PDF page
minutes_url
The minutes PDF, opened at that page
scanned
true when read from a scanned image with OCR

Promises and their deadlines

AI draft84 rows · 26 May 2026 to 30 September 2026

Commitments made in City of Johannesburg council sittings (a date, an amount or a "we will"), with the deadline read as a date, where each stands, later sittings that came back to it, City newsroom reports and matching rows in the City's official performance documents.

Source: AI draft from the City of Johannesburg's council livestreams on YouTube (@CityOfJoburgZA); follow-ups from later sittings and the City's newsroom; official-record matches from the City's SDBIP and JDA quarterly reports.

AI and checks: Every promise is an AI draft (Claude) from the transcript; quote is what was said and time links to it. due_by, latest_by and each follow-up's "by" say whether a field is an AI reading or judgment (with the model) or was checked or corrected by hand. reviewed is false until a person has checked the sitting. clock is counted on the as_of date.

CSV 45 kBJSON 95 kB

Columns (26)
id
Promise id; its page is /promises/<id>/
date
Sitting date
sitting_id
Sitting day id
time
Time on the sitting-day timeline (h:mm:ss)
video_url
The moment on YouTube
page_url
The promise's page here
speaker
Who made it: the executive member when the promise can be tied to one, else the councillor, else as heard
councillor_id
This site's councillor id, when known
office_or_party
Their office(s) that day, or party
speaker_as_heard
The speaker as named in the transcript
what
What was promised (AI summary)
quote
What was said (transcript)
deadline_as_said
The deadline in the speaker's words
amount
Amount, as said
due_date
The deadline read as a date (YYYY-MM-DD; City financial year July-June), blank if none
due_reading
How the date was read
due_by
Whether that reading is AI, checked or corrected by hand
clock
overdue (date passed, nothing found saying done), soon (30 days), later, passed (date passed, said done), sitting (due same or next day), none
clock_days
Days overdue or until due, on the as_of date
latest_status
The newest word on it, from a later sitting or the City
latest_date
Date of that word
latest_by
AI judgment (model) or corrected by hand
later_sittings
Later sitting days that came back to it
city_reports
City newsroom articles about it
official_matches
Rows in the City's official documents matched to it
reviewed
true when a person has checked this sitting

The JSON rows have these fields plus the lists the CSV can only count: followups, city_reports and official_matches.

Sittings

AI draft10 rows · 26 May 2026 to 30 September 2026

Each published City of Johannesburg council sitting day: its livestream videos, a prose summary and counts of chapters, promises and decisions. The JSON nests each day's chapters.

Source: AI draft from the City of Johannesburg's council livestreams on YouTube (@CityOfJoburgZA).

AI and checks: summary and chapters are AI drafts (model named in summary_by and chapters_by); reviewed is false until a person has checked the sitting.

CSV 17 kBJSON 314 kB

Columns (16)
sitting_id
Sitting day id; its page is /sittings/<id>/
date
Date (SAST)
title
Sitting name
meeting
Meeting as named by the City
term
Year the council was elected
duration_seconds
Length of the day's video
videos
YouTube videos, in order, space-separated
chapters
Number of chapters
promises
Number of promises
decisions
Number of decisions (AI-drafted from the video, not the minutes)
summary
Prose summary (AI draft)
summary_by
Model, and the check it passed
chapters_by
Model that drafted chapters, promises and decisions
reviewed
true when a person has checked it
page_url
Its page here
transcript_url
Its full transcript (JSON)

The JSON rows have these fields plus each day's chapters (as in the chapters dataset).

Chapters

AI draft440 rows · 26 May 2026 to 30 September 2026

Every chapter of every published sitting day: start time, title, summary and who spoke, linked to the second of video.

Source: AI draft from the City of Johannesburg's council livestreams on YouTube (@CityOfJoburgZA).

AI and checks: Title, summary and speakers are AI drafts (Claude). A speaker is named only from the councillor list or office holders with a quote from the transcript as evidence; otherwise "Unidentified councillor".

CSV 268 kBJSON 322 kB

Columns (10)
sitting_id
Sitting day id
date
Sitting date
index
Chapter number in the day, from 0
start
Start on the sitting-day timeline (h:mm:ss)
video_url
The start on YouTube
page_url
The chapter on its sitting page here
title
Title (AI draft)
summary
Summary (AI draft)
speakers
Who spoke, "Name (Party)", separated by "; "
councillor_ids
This site's id for each speaker in the same order (blank when not matched), separated by "; "

Money decisions

AI draft53 rows · 31 October 2023 to 30 September 2026

Rand amounts City of Johannesburg council decided on (loans, budgets, transfers and the like), from the signed minutes and from the sitting videos, kept apart by source_type.

Source: The City of Johannesburg's signed council minutes (PDFs on joburg.org.za), read in code (pages around money items read by AI); AI draft from the City of Johannesburg's council livestreams on YouTube (@CityOfJoburgZA).

AI and checks: Every row is AI-extracted (model in "by"); a row is kept only when its quote was found in the minutes page or transcript. Votes from the minutes are as printed. Rows a person rejected are left out; corrected rows say so in "by".

CSV 27 kBJSON 36 kB

Columns (15)
date
Meeting or sitting date
source_type
minutes (signed minutes) or transcript (sitting video)
where
The meeting
item
Agenda item
what
What the money is for (AI summary)
amount
Amount as printed or said
rands
Amount in rand, as a number
kind
Kind of decision
outcome
Outcome
for
Votes for, when counted
against
Votes against, when counted
abstain
Abstentions, when counted
quote
The words in the source
url
The minutes page (PDF) or the moment on YouTube
by
AI draft (model) or corrected by hand

Party positions on items

AI draft646 rows · 26 May 2026 to 30 September 2026

Where parties said they stood (for, against, abstain) on items in City of Johannesburg council sittings, one row per party per item, from the sitting videos. Parties recorded as dissenting in the signed minutes are in the votes dataset's dissent column.

Source: AI draft from the City of Johannesburg's council livestreams on YouTube (@CityOfJoburgZA).

AI and checks: AI draft (model in "by"): each position is kept only when its quote was found in the transcript and names the party. Positions a person rejected are left out.

CSV 179 kBJSON 266 kB

Columns (13)
date
Sitting date
sitting_id
Sitting day id
item
Agenda item
title
Item title
method
How it was decided (voice, count, ...)
outcome
Outcome
party
Party
side
for, against or abstain, as stated
kind
How the position was stated
quote
What was said
time
Time on the sitting-day timeline
video_url
The moment on YouTube
by
AI draft (model)

Transcripts

AI draft10 sitting days · 26 May 2026 to 30 September 2026

Every line of each published sitting day, one JSON file per day. Each line has start and end (seconds on the day's timeline: its videos laid end to end, listed in the file with their YouTube links), the video it is in, the language when it isn't English, and the text. Speakers are not in the transcript; they are in the chapters dataset.

Source: AI draft from the City of Johannesburg's council livestreams on YouTube (@CityOfJoburgZA). AI and checks: machine transcription (model named in each file), not checked line by line; names and non-English speech are the weak points.

Not included: anyone's contact details (never collected), the audio, and drafts or pairs a person rejected. Want something on a page in your own story instead? Promise, councillor and sitting pages have an "Embed this" card.