Wordle creates word clouds based on the frequency on words in a text, similar to tag clouds. What makes it unique is that it can lay out words in arbitrary directions without too much white space. See the gallery for many examples.

Given a list of words together with their frequency, is there some package that provides at least some of the functionality in (La)TeX? If not, is there some way to abuse the TeX layout engine to produce word clouds?

(This is not meant as advertisment for wordle, I just do not know of anything that is similar.)


3 Answers 3


Most word cloud generator simply generate a scaled word according to its relative frequency in the text, and then pack everything together in a nice way. Wordle really shines in using the shape of each letter rather than the bounding box. That is the reason that the resultant word clouds have very little white space.

AFAIU, TeX only knows the bounding box of a word. So, even if the wordle algorithm were known (is it?), we need more hooks to implement it in TeX. Perhaps luatex+mplib can be used to access the shape of the glyph, but I do not know the details.

The easier option is to use worldle to generate a png and simply include the png in your tex file. The java file for the engine that powers wordle is available from http://www.alphaworks.ibm.com/tech/wordcloud (you need to register first). Then, it is a simple matter of providing some plumbing so that

  lots of text

stores the text in an external file, runs it through wordle, and includes the resultant png. For example, if you want to do this in ConTeXt

  1. Download the IBM Word Cloud engine. After unzipping the files, I removed spaces from the folder names and renamed it to "IBM-Word-Cloud".

  2. Download the externalfilter module

  3. Then you can create word clouds as follows


      [filtercommand=/opt/java/jre/bin/java -jar $HOME/IBM-Word-Cloud/ibm-word-cloud.jar
        -c $HOME/IBM-Word-Cloud/examples/configuration.txt
        -w 800 -h 600
        -o \externalfilteroutputfile\space
        -i \externalfilterinputfile,


and then use

  lots of words

See this blog post for more details.

  • 6
    I didn't know that the wordle engine was available for download. Thanks for the link!
    – Caramdir
    Commented Aug 3, 2010 at 21:39
  • 2
    A proof of concept: randomdeterminism.wordpress.com/2010/08/03/… and a working example (with ibm-word-cloud.jar moved to $HOME/bin and configuration.txt moved to $HOME/.config/IBM-Word-Cloud) github.com/adityam/filter/blob/master/tests/wordcloud.tex
    – Aditya
    Commented Aug 3, 2010 at 23:04
  • Thank you again. Could you please add the link directly to the answer (so that it is more obvious for other people coming here, e.g. via google).
    – Caramdir
    Commented Aug 4, 2010 at 10:49
  • I added actual code in the answer with a link to the blog post.
    – Aditya
    Commented Aug 4, 2010 at 14:18
  • 3
    Is there a way of generating a wordle image that isn't a bitmap? Commented Aug 4, 2010 at 19:23

This is my first post. Yesterday I saw this question and I made some PERL code. I know is not exactly the same than you want, and I know it would be better to do it in TeX, but maybe this is useful for some people. It has two options:

  • Make wordcloud of index entries:

    ./latextotagcloud.pl index file.tex > file.html

  • Make wordcloud of cite authors:

    ./latextotagcloud.pl citea file.tex > file.html

  • Make wordcloud of cite documents:

    ./latextotagcloud.pl cited file.tex > file.html

NEW CODE (v 2.0) UPDATED OCTOBER 18, 2011 This new code allows color images I like them because a small word can be highlighted by it's color. I saw in monocolor clouds that long words catch eye because of it's width.

#!/usr/bin/perl -w
#v. 2.0
#(c) Xavier de Blas, 2011. This code is GPL 2.0.
use HTML::TagCloud_colors;

$background = "#ffffff"; $color_small ="#333333"; $color_big ="#ff0000";

#$background = "#000066"; $color_small ="white"; $color_big ="red";
#$background = "#ffffff"; $color_small ="#333333"; $color_big ="blue";

if( @ARGV != 2 or ( $ARGV[0] ne "index" and $ARGV[0] ne "citea" and $ARGV[0] ne "cited") ) {
  print STDERR "Usage:\n ./latextotagcloud.pl option file.tex > file.html     \n(option: index or citea or cited)\n";
$option = shift(@ARGV);
undef $/;
while(<IN>) {
  if($option eq "index") {
  while($_ =~ /\\index{([^@!}\|]*)([^}]*)}/g) {
#   while($_ =~ /\\index{([^!}\|]*)([^}]*)}/g) {        
      $matched = $1;
      unless ($2 =~ m/^\|see/) { #don't use the "see other concept" entries
        $matched =~ s/ /-/g;     #Converts: Index A B -> Index-A-B
#        if($matched =~ m/@/) { ($matchedSorting, $matched)=split(/@    /,$matched); }
  } elsif($option eq "citea") {
      #next line gets "Bosco" in "Bosco1993", but "W3Schools" is written to match "W3Schools2001"
      while($_ =~ /\\cite[^{]*{(W3Schools|[A-Za-z'\-]+)[^}]*}/g) {
  } elsif($option eq "cited") {
  while($_ =~ /\\cite[^{]*{([A-Za-z0-9'\-]+)[^}]*}/g) {
print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print "<style type=\"text/css\">\n  \@import       url(latextotagcloud.css);\n</style>";

$maxLevels = 1;
foreach(keys %seen) {
        if($seen{$_} > $maxLevels) { $maxLevels = $seen{$_}; }
my $cloud = HTML::TagCloud->new(levels=>$maxLevels);
foreach(sort keys %seen) {
        $latinized = $_;
        $latinized =~ s/'a/á/g;
        $latinized =~ s/'e/é/g;
        $latinized =~ s/'i/í/g;
        $latinized =~ s/'o/ó/g;
        $latinized =~ s/'u/ú/g;
        $cloud->add("$latinized", "", $seen{$_});

print $cloud->html_and_css();#if put a value, limit to that number of tags

open RFILE,">colors.R";
print RFILE "as.data.frame(colorRampPalette(c('$color_small', '$color_big'))($maxLevels+1))";   #ELMILLOR
close RFILE;

system("R CMD BATCH --slave --no-timing colors.R latextotagcloud_pre.css");

open CSSFILE1,"latextotagcloud_pre.css";
open CSSFILE2,">latextotagcloud.css";

$line = 0;
print CSSFILE2 "<style type=\"text/css\">\n
#htmltagcloud {
  text-align:  center;
  line-height: 1; 
body { background: $background; } 

        unless($line == 0) {
                $_ =~ /#(......)/;
                print CSSFILE2 "span.tagcloud" . ($line-1) ." a {text-decoration: none; color: #$1;}\n";
        $line ++;
print CSSFILE2 "</style>";

close CSSFILE1;
close CSSFILE2;


#!/usr/bin/perl -w
#(c) Xavier de Blas, 2011. This code is GPL 2.0.
use HTML::TagCloud;

if( @ARGV != 2 or ( $ARGV[0] ne "index" and $ARGV[0] ne "citea" and $ARGV[0] ne "cited") ) {
  print STDERR "Usage:\n ./latextotagcloud.pl option file.tex > file.html \n(option: index or citea or cited)\n";
$option = shift(@ARGV);
undef $/;
while(<IN>) {
  if($option eq "index") {
    while($_ =~ /\\index{([^@!}\|]*)[^}]*}/g) {
      ($underscored = $1) =~ s/ /_/g;   #Converts: Index A B -> Index_A_B
  } elsif($option eq "citea") {
      #next line gets "Bosco" in "Bosco1993", but "W3Schools" is written to match "W3Schools2001"
      while($_ =~ /\\cite[^{]*{(W3Schools|[A-Za-z\-]+)[^}]*}/g) {
  } elsif($option eq "cited") {
      while($_ =~ /\\cite[^{]*{([A-Za-z0-9\-]+)[^}]*}/g) {
my $cloud = HTML::TagCloud->new();
foreach(sort keys %seen) { $cloud->add("$_", "", $seen{$_}); }
print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print $cloud->html_and_css();

save in in a file named:


and do:

chmod +x latextotagcloud.pl

you need to have libhtml-tagcloud-perl (and obviously perl) installed.

With new 2.0 code you will need R installed (eg. instal r-base on debian/ubuntu systems) With new 2.0 code you also need to modify libtagcloud. Instructions for Debian/Ubuntu:

  1. dpkg -L libhtml-tagcloud-perl
  2. Find: TagCloud.pm
  3. In Linux Mint (Debian/Ubuntu) is here: /usr/share/perl5/HTML/TagCloud.pm
  4. Go to /usr/share/perl5/HTML and copy the file:
  5. sudo cp TagCloud.pm TagCloud_colors.pm
  6. Change this in TagCloud_colors:
foreach my $level (0 .. $self->{levels}) {
  my $font = 12 + $level; 

To this:

my $fontMin = 12; 
my $fontMax = 36;
my $fontRang = $fontMax - $fontMin; 
foreach my $level (0 .. $self->{levels}) {
  #my $font = 12 + $level;    
  my $font = $fontMin + ( $fontRang * $level / $self->{levels} );  

With this you will have an html cloud, to have it nicer in your document, you can:

  1. Open in browser, print as PDF.
  2. Open PDF in Inkscape, select all words (cutoff blank paper), properties (adjust to selection), print as PDF.
  3. Include PDF in your LaTeX or LyX document.

Here is the result on the authors cited on my PhD document today (v1.0):

enter image description here

Result of (v2.0):

enter image description here

enter image description here

Maybe you can use the same and the connect to Wordle, I haven't done this because Worlde is not free software.

Hope it helps

  • The previous requires installing the following package: libhtml-tagcloud-perl
    – user8632
    Commented Oct 16, 2011 at 16:14
  • Can't exec "R": No such file or directory at ./latextotagcloud.pl line 67, <IN> chunk 1., is it looking for the statistics programme "R"?
    – EricR
    Commented Feb 13, 2012 at 17:33
  • Nice. I know the lack of vertical words isn't as trendy, but it sure is a lot more readable. Good point about wordle not being free, too.
    – naught101
    Commented Aug 2, 2012 at 1:50
  • @EricR Yes, you have to install R. For me on ubuntu, sudo apt install r-base Commented Sep 26, 2017 at 17:20
  • Well, thanks for the code, I think I will try something else because I don't just want index and citea, I really want the whole document aside from LaTeX commands. Commented Sep 26, 2017 at 17:22

Since wordle seems to be hard to find, here is another (non LaTeX) tool to create nice images that you can download. It's quite customizable (you can define multiple orientations for the text, and choose the font, the size dynamics, the shape of the spiral, the number of words...)

It is based on the open source d3-cloud algorithm. The principle is explained here, in case someone wants to try to implement it in Tikz ^^


enter image description here

enter image description here

  • thanks for the link! Commented Mar 11, 2023 at 8:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .