Text Technology Lab · Goethe University Frankfurt

TTLabTweetCorpus

Download posts.
Connect corpora.

TTLabTweetCorpus contains 39,546 public X posts, including 19,056 with media information. More than 15,000 posts come from German politicians during the 2024–2025 election period, and the corpus is linked to GerParCor. Its download component is TTLabTweetCrawler.

  • 39,546+tweets
  • 19,056with media information
  • 15,000+political tweets · 2024–2025

bash — TTLabTweetCrawler

$ ttlab-collect-tweets per-query \
  --query "WM2026" \
  --media-only \
  --exclude-retweets \
  --max-tweets 2000 \
  --output output/wm2026

 Saved page 0001 · 100 posts
 Following pagination token…
 Preserved media + referenced posts
Token read from X_BEARER_TOKEN
Tweet + media downloadGerParCor connectionDUUI processing

Research workflow

Four compatible stages

TTLabTweetCrawler provides the download layer of TTLabTweetCorpus; GerParCor and DUUI connect the corpus to parallel text and multimodal analysis workflows.

01

Download tweets + media

Collect timelines per user or search by query with a media-only filter. Preserve attached images and videos as Base64 or extracted files.

TTLabTweetCrawler
02

Connect with GerParCor

The collected social-media data can be linked with parliamentary records from the German Parliamentary Corpus.

GerParCor ↗
03

Annotate with DUUI

The DUUI pipeline is configured and executed in Java. DUUI-spaCy first segments each tweet into sentences before the selected emotion, topic, and sentiment models run. DUUI provides more components and models; the paper uses the pipeline documented below.

DUUI ↗
04A

Compare nine text models

Three emotion, three topic, and three sentiment models annotated 33,921 tweets. Each model was then predicted from the outputs of the other eight.

3 emotion · 3 topic · 3 sentiment
04B

Process images + video via DUUI

Attached images and video frames can be processed with vision-language models served through vLLM.

vLLM · image · video

Study model selection

Models used for automatic annotation

The study combines nine text models for emotion, topic, and sentiment with one multimodal vision-language model for structured image and video annotation.

Multimodal model selection · 04B

Image and video annotation with vLLM

Multimodal Automatic Annotation ↗ serves Qwen2.5-VL-3B-Instruct through vLLM for structured multimodal classification.

LevelL1
MethodLLM
TaskMulti-class classification
ModelQwen2.5-VL-3B-Instruct
E
Emotion

anger · sadness · apprehension · confusion · happiness

S
Sentiment

positive · neutral · negative

T
Topic · DDC Level 1

000 · 100 · 200 · 300 · 400 · 500 · 600 · 700 · 800 · 900

For each task, the model returns a predicted label, a confidence distribution over all labels, and a brief evidence-based explanation in one valid JSON object.

Open image prompt
You are an AI system tasked with performing multimodal analysis on a media input (image). Your responsibilities include:

1. **Emotion Classification**
Identify one or more emotional states expressed visually in the image. Use the following emotion labels:
- anger (AN)
- sadness (SD)
- apprehension (AP)
- confusion (CO)
- happiness (HA)

2. **Sentiment Analysis**
Assess the overall sentiment conveyed by the image. Choose from:
- positive
- neutral
- negative

3. **Topic Classification (Based on DDC Level 1)**
Determine the most relevant topic of the image using one of the following Dewey Decimal classes:
- 000: Computer science, information, and general works
- 100: Philosophy and psychology
- 200: Religion
- 300: Social sciences
- 400: Language
- 500: Science
- 600: Technology
- 700: Arts and recreation
- 800: Literature
- 900: History and geography

You must return the result in **valid JSON format**, with the following components for each of the three tasks:
- The **predicted label**
- A **confidence distribution** over all possible labels (values between 0 and 1, summing to 1)
- A **brief explanation**, grounded in specific visual or contextual cues observed in the image

The output must follow this structure:
{
  "emotion": {
    "predicted": "<label>",
    "confidence_distribution": {
      "anger": <float>,
      "sadness": <float>,
      "apprehension": <float>,
      "confusion": <float>,
      "happiness": <float>
    },
    "explanation": "<evidence-based explanation>"
  },
  "sentiment": {
    "predicted": "<label>",
    "confidence_distribution": {
      "positive": <float>,
      "neutral": <float>,
      "negative": <float>
    },
    "explanation": "<evidence-based explanation>"
  },
  "topic": {
    "predicted": "<label>",
    "confidence_distribution": {
      "000": <float>,
      "100": <float>,
      "200": <float>,
      "300": <float>,
      "400": <float>,
      "500": <float>,
      "600": <float>,
      "700": <float>,
      "800": <float>,
      "900": <float>
    },
    "explanation": "<evidence-based explanation>"
  }
}

Important Constraints:

    All outputs must be grounded in the specific content of the image provided.

    You must not copy or reuse example values.

    The confidence values must reflect the actual visual cues in the image.

    If the image contains multiple people or elements, base the classification on the dominant or most salient features, but take all visual evidence into account when calculating confidence.

Return only the JSON object. Do not include commentary or template examples.
Open video prompt
You are an AI system tasked with performing multimodal analysis on a media input (video and accompanying audio if exists). Your responsibilities include:

1. **Emotion Classification**
Identify one or more emotional states expressed visually in the image. Use the following emotion labels:
- anger (AN)
- sadness (SD)
- apprehension (AP)
- confusion (CO)
- happiness (HA)

2. **Sentiment Analysis**
Assess the overall sentiment conveyed by the image. Choose from:
- positive
- neutral
- negative

3. **Topic Classification (Based on DDC Level 1)**
Determine the most relevant topic of the image using one of the following Dewey Decimal classes:
- 000: Computer science, information, and general works
- 100: Philosophy and psychology
- 200: Religion
- 300: Social sciences
- 400: Language
- 500: Science
- 600: Technology
- 700: Arts and recreation
- 800: Literature
- 900: History and geography

You must return the result in **valid JSON format**, with the following components for each of the three tasks:
- The **predicted label**
- A **confidence distribution** over all possible labels (values between 0 and 1, summing to 1)
- A **brief explanation**, grounded in specific visual or contextual cues observed in the image

The output must follow this structure:
{
  "emotion": {
    "predicted": "<label>",
    "confidence_distribution": {
      "anger": <float>,
      "sadness": <float>,
      "apprehension": <float>,
      "confusion": <float>,
      "happiness": <float>
    },
    "explanation": "<evidence-based explanation>"
  },
  "sentiment": {
    "predicted": "<label>",
    "confidence_distribution": {
      "positive": <float>,
      "neutral": <float>,
      "negative": <float>
    },
    "explanation": "<evidence-based explanation>"
  },
  "topic": {
    "predicted": "<label>",
    "confidence_distribution": {
      "000": <float>,
      "100": <float>,
      "200": <float>,
      "300": <float>,
      "400": <float>,
      "500": <float>,
      "600": <float>,
      "700": <float>,
      "800": <float>,
      "900": <float>
    },
    "explanation": "<evidence-based explanation>"
  }
}

Important Constraints:

    All outputs must be grounded in the specific content of the image provided.

    You must not copy or reuse example values.

    The confidence values must reflect the actual visual cues in the image.

    If the image contains multiple people or elements, base the classification on the dominant or most salient features, but take all visual evidence into account when calculating confidence.

Return only the JSON object. Do not include commentary or template examples.
Open Qwen2.5-VL citation and BibTeX
Bai et al. (2025) · Qwen2.5-VL Technical Report
@misc{Bai:et:al:2025,
  title         = {Qwen2.5-VL Technical Report},
  author        = {Shuai Bai and Keqin Chen and Xuejing Liu and Jialin Wang and Wenbin Ge and Sibo Song and Kai Dang and Peng Wang and Shijie Wang and Jun Tang and Humen Zhong and Yuanzhi Zhu and Mingkun Yang and Zhaohai Li and Jianqiang Wan and Pengfei Wang and Wei Ding and Zheren Fu and Yiheng Xu and Jiabo Ye and Xi Zhang and Tianbao Xie and Zesen Cheng and Hang Zhang and Zhibo Yang and Haiyang Xu and Junyang Lin},
  year          = {2025},
  eprint        = {2502.13923},
  archivePrefix = {arXiv},
  primaryClass  = {cs.CV},
  url           = {https://arxiv.org/abs/2502.13923}
}

Text model selection · 04A

Nine models used for automatic text annotation

DUUI contains more components and supports more models than those listed here. For the associated paper, we used exactly the nine models below through the linked DUUI components.

00
Sentence segmentation with spaCy

Before emotion, topic, and sentiment annotation, the DUUI-spaCy component ↗ splits every tweet into sentences [P1].

TweetspaCy sentences9 text models
IDTaskDUUI Model NameShort descriptionDUUI componentCitation
Emotion Models E1–E3
E1Emotion finetuned-twitter-xlm-roberta-base-emotion Twitter-domain XLM-RoBERTa fine-tuned for multilingual emotion classification. Emotion ↗[E1]
E2Emotion dreamy-xlm-roberta-emotion DReAMy XLM-RoBERTa Large model for detecting emotion presence in multilingual text. Emotion ↗[E2]
E3Emotion pol_emo_mDeBERTa Multilingual mDeBERTa trained on political communication to identify eight discrete emotions. Emotion ↗[E3]
Topic Models T1–T3
T1Topic text2ddc fastText-based topic annotation mapped to the Dewey Decimal Classification; provided through its dedicated DUUI component. DDC fastText ↗[T1]
T2Topic multilingual-iptc-media-topic-classifier XLM-RoBERTa Large classifier for the 17 top-level IPTC Media Topic categories. Topic ↗[T2]
T3Topic tweet-topic-large-multilingual Large multilingual topic classifier developed for social-media posts and cross-lingual analysis. Topic ↗[T3]
Sentiment Models S1–S3
S1Sentiment citizenlab-twitter-xlm-roberta-base-sentiment-finetunned CitizenLab multilingual XLM-RoBERTa sentiment model fine-tuned on Twitter data. Sentiment ↗[S1]
S2Sentiment distilbert-base-multilingual-cased-sentiment Compact multilingual DistilBERT student model for sentiment classification. Sentiment ↗[S2]
S3Sentiment twitter-xlm-roberta-base-sentiment XLM-T sentiment classifier based on multilingual Twitter language-model pretraining. Sentiment ↗[S3]
A
Cross-model prediction

We trained nine classifiers—one for each annotation model. Each classifier predicted the annotations of one model from the outputs of the other eight.

8 model outputsClassifierPredicted model output
Open model citations and BibTeX

Citations for the study selection

Each BibTeX record can be copied independently. P1 identifies preprocessing; E, T, and S identify the model groups.

P1Honnibal, Montani et al. (2020)
@misc{Honnibal:Montani:et:al:2020,
  author = {Honnibal, Matthew and Montani, Ines and Van Landeghem, Sofie and Boyd, Adriane},
  doi    = {10.5281/zenodo.1212303},
  title  = {{spaCy: Industrial-strength Natural Language Processing in Python}},
  year   = {2020}
}
E1Shivshankar (2023)
@misc{Shivshankar:2023,
  author    = {Shivshankar},
  title     = {finetuned-twitter-xlm-roberta-base-emotion},
  year      = {2023},
  url       = {https://huggingface.co/02shanky/finetuned-twitter-xlm-roberta-base-emotion},
  publisher = {Hugging Face}
}
E2Bertolini et al. (2024)
@article{Bertolini:et:al:2024,
  title   = {DReAMy: a library for the automatic analysis and annotation of dream reports with multilingual large language models},
  journal = {Sleep Medicine},
  volume  = {115},
  pages   = {406--407},
  year    = {2024},
  issn    = {1389-9457},
  doi     = {10.1016/j.sleep.2023.11.1092},
  url     = {https://www.sciencedirect.com/science/article/pii/S1389945723015186},
  author  = {L. Bertolini and A. Michalak and J. Weeds}
}
E3Widmann & Wich (2023)
@article{Widmann:Wich:2023,
  title   = {Creating and Comparing Dictionary, Word Embedding, and Transformer-Based Models to Measure Discrete Emotions in German Political Text},
  volume  = {31},
  doi     = {10.1017/pan.2022.15},
  number  = {4},
  journal = {Political Analysis},
  author  = {Widmann, Tobias and Wich, Maximilian},
  year    = {2023},
  pages   = {626--641}
}
T1Uslu et al. (2018)
@inproceedings{Uslu:et:al:2018,
  author    = {Tolga Uslu and Alexander Mehler and Andreas Niekler and Daniel Baumartz},
  title     = {Towards a {DDC}-based Topic Network Model of Wikipedia},
  booktitle = {Proceedings of 2nd International Workshop on Modeling, Analysis, and Management of Social Networks and their Applications (SOCNET 2018)},
  url       = {https://www.texttechnologylab.org/wp-content/uploads/2018/03/TowardsDDC.pdf},
  year      = {2018}
}
T2Kuzman & Ljubešić (2025)
@article{Kuzman:Ljubesic:2025,
  title     = {LLM Teacher-Student Framework for Text Classification With No Manually Annotated Data: A Case Study in IPTC News Topic Classification},
  volume    = {13},
  issn      = {2169-3536},
  doi       = {10.1109/ACCESS.2025.3544814},
  journal   = {IEEE Access},
  publisher = {IEEE},
  author    = {Kuzman, Taja and Ljube{\v{s}}i{\'c}, Nikola},
  year      = {2025},
  pages     = {35621--35633}
}
T3Antypas et al. (2024)
@inproceedings{Antypas:et:al:2024,
  title     = {Multilingual Topic Classification in {X}: Dataset and Analysis},
  author    = {Antypas, Dimosthenis and Ushio, Asahi and Barbieri, Francesco and Camacho-Collados, Jose},
  booktitle = {Proceedings of the 2024 Conference on Empirical Methods in Natural Language Processing},
  month     = {nov},
  year      = {2024},
  address   = {Miami, Florida, USA},
  publisher = {Association for Computational Linguistics},
  url       = {https://aclanthology.org/2024.emnlp-main.1123/},
  doi       = {10.18653/v1/2024.emnlp-main.1123},
  pages     = {20136--20152}
}
S1CitizenLabDotCo (2022)
@misc{Citizenlab:2022,
  author    = {CitizenLabDotCo},
  title     = {CitizenLab multilingual XLM-Roberta sentiment},
  year      = {2022},
  url       = {https://huggingface.co/citizenlab/twitter-xlm-roberta-base-sentiment-finetunned},
  publisher = {Hugging Face}
}
S2Schmid (2022)
@misc{Schmid:2022,
  author    = {Schmid, Philipp},
  title     = {distilbert-base-multilingual-cased-sentiment},
  year      = {2022},
  url       = {https://huggingface.co/philschmid/distilbert-base-multilingual-cased-sentiment},
  publisher = {Hugging Face}
}
S3Barbieri et al. (2022)
@inproceedings{Barbieri:et:al:2022,
  title     = {{XLM}-{T}: Multilingual Language Models in {Twitter} for Sentiment Analysis and Beyond},
  author    = {Barbieri, Francesco and Espinosa Anke, Luis and Camacho-Collados, Jose},
  booktitle = {Proceedings of the Thirteenth Language Resources and Evaluation Conference},
  month     = {jun},
  year      = {2022},
  address   = {Marseille, France},
  publisher = {European Language Resources Association},
  url       = {https://aclanthology.org/2022.lrec-1.27/},
  pages     = {258--266}
}

Five-minute setup

One package.
Explicit credentials.

Requires Python 3.10 or newer. Clone the GitHub repository and install its Python package in an isolated environment. This provides the tweet, media, GerParCor download, and sentence-matching commands used throughout the workflow below.

Security note

Prefer an environment variable. A token passed with --bearer-token may be visible in shell history and the process list.

Install from GitHub
git clone https://github.com/texttechnologylab/TTLabTweetCorpus.git
cd TTLabTweetCorpus
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install --editable ./python

export X_BEARER_TOKEN="YOUR_BEARER_TOKEN"

Command recipes

Choose a workflow stage

USER TIMELINE

Collect by numeric user ID

Downloads the user's posts between two RFC3339 timestamps. Replies and retweets are included unless excluded explicitly.

Terminal
ttlab-collect-tweets per-user \
  --user-id 123456789 \
  --start-time "2025-01-01T00:00:00Z" \
  --end-time "2025-02-20T00:00:00Z" \
  --max-tweets 500 \
  --output output/example_user
SEARCH

Collect original posts with media

--media-only adds has:media; --exclude-retweets adds -is:retweet. The original query remains readable.

Terminal
ttlab-collect-tweets per-query \
  --query "WM2026" \
  --media-only \
  --exclude-retweets \
  --max-tweets 2000 \
  --page-size 100 \
  --output output/wm2026
BASE64

Embed images and videos

Reads saved API pages, selects direct image URLs or the highest-bitrate MP4 variant, and writes enriched copies.

Terminal
ttlab-download-media \
  --input output/wm2026 \
  --output output/wm2026_base64 \
  --timeout 120
FILES

Restore binary media

Decodes Base64 and names output by tweet ID. Multiple attachments receive deterministic _1, _2 suffixes.

Terminal
ttlab-extract-media \
  --input output/wm2026_base64 \
  --output output/wm2026_media
GERPARCOR XMI

Download parliamentary documents

Downloads every XMI document for one parliament and an inclusive date range. Use --list-only to preview the selection. Individual files are also available from the manual GerParCor web interface ↗.

Terminal
ttlab-download-gerparcor \
  --parliament Bundestag \
  --start 2010-01-01 \
  --end 2010-01-31 \
  --output gerparcor_documents \
  --insecure
COSINE SIMILARITY

Match complete tweets to XMI sentences

Embeds complete tweets and individual GerParCor sentences. Use --top-k for compact results or --all-matches for exhaustive comparisons on small datasets.

Terminal
ttlab-match-tweets-xmi \
  --tweets tweet_json_directory \
  --xmi xmi_directory \
  --output output/matches.json.gz \
  --top-k 5 \
  --minimum-score 0.4 \
  --device cpu

Complete CLI reference

Every parameter, in one place

Required arguments are marked. Defaults shown here match the command-line help.

TTLAB-DOWNLOAD-MEDIA

Media download & Base64

Reads collected .json.gz pages and writes enriched copies.

-i, --inputrequired

Input page or directory.

-o, --outputrequired

Separate directory for enriched pages.

--recursiveoff

Search nested input directories.

--timeout60 sec

Timeout for each image/video request.

--max-bytesunlimited

Reject an individual media file above this byte count.

--fail-fastoff

Stop on first error instead of recording it in JSON.

Example
ttlab-download-media \
  -i output/wm2026 \
  -o output/wm2026_base64 \
  --recursive \
  --timeout 120 \
  --max-bytes 104857600
TTLAB-EXTRACT-MEDIA

Media extraction

Decodes embedded Base64 data into image and video files.

-i, --inputrequired

Enriched page or directory.

-o, --outputrequired

Directory receiving binary media files.

--recursiveoff

Search nested input directories.

One file123456.jpgMultiple123456_1.jpg123456_2.mp4
TTLAB-COLLECT-USER-IDS

User lookup

Resolves usernames and preserves X lookup errors.

usernamesoptional*

One or more names, with or without @.

-i, --inputoptional*

JSON or text file containing usernames.

-o, --outputrequired

Destination JSON file.

--bearer-tokenenvironment

Token or X_BEARER_TOKEN.

--timeout30 sec

HTTP request timeout.

* Supply direct usernames, an input file, or both.

TTLAB-DOWNLOAD-GERPARCOR

GerParCor download

Queries document metadata and downloads XMI files for an inclusive date range.

--parliamentrequired

GerParCor parliament name.

--startrequired

Inclusive start date in YYYY-MM-DD format.

--endrequired

Inclusive end date in YYYY-MM-DD format.

--outputgerparcor_documents

Directory receiving downloaded XMI files.

--list-onlyoff

Print matching documents without downloading them.

--insecureoff

Disable TLS certificate verification only when required.

Example
ttlab-download-gerparcor \
  --parliament PARLIAMENT_NAME \
  --start YYYY-MM-DD \
  --end YYYY-MM-DD \
  --output xmi_directory \
  --list-only
TTLAB-MATCH-TWEETS-XMI

Tweet-sentence matching

Computes normalized embeddings and cosine similarities between complete tweets and individual XMI sentences.

--tweetsrequired

Tweet JSON/JSON.GZ file or directory.

--xmirequired

XMI/XMI.GZ file or directory.

--outputrequired

Destination JSON or compressed JSON.GZ file.

--modelmultilingual MiniLM

Sentence Transformers model name or local model path.

--top-k5

Highest-scoring sentence matches retained per tweet.

--all-matchesoff

Retain every comparison instead of applying the top-k limit.

--minimum-score-1

Discard cosine scores below this threshold.

--embedding-batch-size64

Texts encoded in one model batch.

--tweet-chunk-size2048

Tweet embeddings compared in one matrix chunk.

--location-rootcurrent directory

Base directory for source paths stored in the result.

--include-textoff

Copy tweet and sentence text into the result.

--deviceautomatic

Execution device such as cpu, cuda, or mps.

Example
ttlab-match-tweets-xmi \
  --tweets tweet_json_directory \
  --xmi xmi_directory \
  --output output/matches.json.gz \
  --model MODEL_NAME \
  --top-k 5 \
  --device cpu

Practical reference

Behavior you can rely on

Pagination

The collector follows every meta.next_token until results end or a configured tweet/page limit is reached.

Page storage

Each response remains a separate .json.gz file, preserving data, includes, meta, and partial errors.

Rich defaults

Public Articles, media metadata, Notes, cards, Communities, metrics, authors, places, polls, and references are requested.

!

Failure visibility

HTTP failures stop collection clearly. Media failures can be recorded per item so that the remaining dataset still completes.

Output naming

Predictable by design

output/wm2026_media/ ├── 1893300012345678901.jpg ├── 1893300098765432102_1.jpg └── 1893300098765432102_2.mp4

Usage awareness

Set limits before large runs

X API pricing is controlled by X and may change. Use --max-tweets together with --page-size, monitor the Developer Console, and configure an account spending limit.

Current X API pricing ↗

Research software

Cite the associated paper

TTLabTweetCorpus accompanies an accepted paper at KONVENS 2026. A publication link and DOI will be added when available.

KONVENS 2026Hamburg, GermanyAcceptedSoftware: AGPL-3.0-only ↗

Associated publication

Extending a Parliamentary Corpus with MPs’ Tweets: Automatic Annotation and Evaluation Using TTLABTWEETCORPUS

Mevlüt Bagci · Ali Abusaleh · Daniel Baumartz · Alexander Mehler · Giuseppe Abrami · Maxim Konca

CITATION.cff BibTeX
@inproceedings{bagci:et:al:2026,
  title     = {Extending a Parliamentary Corpus with {MP}s{\textquoteright} Tweets: Automatic Annotation and Evaluation Using {TTLABTWEETCORPUS}},
  author    = {Mevlüt Bagci and Ali Abusaleh and Daniel Baumartz and Alexander Mehler and Giuseppe Abrami and Maxim Konca},
  booktitle = {KONVENS 2026 - Context matters: NLP beyond Text},
  year      = {2026},
  address   = {Hamburg, Germany},
  note      = {Accepted}
}

Ready to collect?

Start with ten posts.
Scale when the output looks right.

ttlab-collect-tweets per-query --query "WM2026" --max-tweets 10 --page-size 10 --output output/test