True color (24-bit) at Wikipedia is described in pertinent part as

24 bits almost always uses 8 bits of each of R, G, B. As of 2018 24-bit color depth is used by virtually every computer and phone display and the vast majority of image storage formats. Almost all cases where there are 32 bits per pixel mean that 24 are used for the color, and the remaining 8 are the alpha channel or unused.

224 gives 16,777,216 color variations. The human eye can discriminate up to ten million colors[10] and since the gamut of a display is smaller than the range of human vision, this means this should cover that range with more detail than can be perceived. ...


Macintosh systems refer to 24-bit color as "millions of colors". The term "True color" is sometime used to mean what this article is calling "Direct color".[13] It is also often used to refer to all color depths greater or equal to 24.

An image containing all 16,777,216 colors

All 16,777,216 colors


Write a program which generates and returns all 16,777,216 color variations within an array as strings in the CSS rgb() function

5.1. The RGB functions: rgb() and rgba()

The rgb() function defines an RGB color by specifying the red, green, and blue channels directly. Its syntax is:

rgb() = rgb( <percentage>{3} [ / <alpha-value> ]? ) |
        rgb( <number>{3} [ / <alpha-value> ]? )
<alpha-value> = <number> | <percentage>

The first three arguments specify the red, green, and blue channels of the color, respectively. 0% represents the minimum value for that color channel in the sRGB gamut, and 100% represents the maximum value. A <number> is equivalent to a <percentage>, but with a different range: 0 again represents the minimum value for the color channel, but 255 represents the maximum. These values come from the fact that many graphics engines store the color channels internally as a single byte, which can hold integers between 0 and 255. Implementations should honor the precision of the channel as authored or calculated wherever possible. If this is not possible, the channel should be rounded to the closest value at the highest precision used, rounding up if two values are equally close.

The final argument, the <alpha-value>, specifies the alpha of the color. If given as a <number>, the useful range of the value is 0 (representing a fully transparent color) to 1 (representing a fully opaque color). If given as a , 0% represents a fully transparent color, while 100% represents a fully opaque color. If omitted, it defaults to 100%.

Values outside these ranges are not invalid, but are clamped to the ranges defined here at computed-value time.

For legacy reasons, rgb() also supports an alternate syntax that separates all of its arguments with commas:

rgb() = rgb( <percentage>#{3} , <alpha-value>? ) |
        rgb( <number>#{3} , <alpha-value>? )

Also for legacy reasons, an rgba() function also exists, with an identical grammar and behavior to rgb().

or RGB hexadecimal notation #RRGGBB format

5.2. The RGB hexadecimal notations: #RRGGBB

The CSS hex color notation allows a color to be specified by giving the channels as hexadecimal numbers, which is similar to how colors are often written directly in computer code. It’s also shorter than writing the same color out in rgb() notation.

The syntax of a <hex-color> is a <hash-token> token whose value consists of 3, 4, 6, or 8 hexadecimal digits. In other words, a hex color is written as a hash character, "#", followed by some number of digits 0-9 or letters a-f (the case of the letters doesn’t matter - #00ff00 is identical to #00FF00).

The number of hex digits given determines how to decode the hex notation into an RGB color:

6 digits

The first pair of digits, interpreted as a hexadecimal number, specifies the red channel of the color, where 00 represents the minimum value and ff (255 in decimal) represents the maximum. The next pair of digits, interpreted in the same way, specifies the green channel, and the last pair specifies the blue. The alpha channel of the color is fully opaque.

In other words, #00ff00 represents the same color as rgb(0 255 0) (a lime green).

See Editor's Draft of CSS Color Module Level 4


CSS rgb() function (space character can be substituted for comma character, e.g., rgb(0 255 0))

// `rgb()` `<percentage>` as strings in resulting array
['rgb(0%,0%,0%)', ...,'rgb(0%,255%,0)', ...'rgb(255,255,255)']

// `rgb()` `<number>` as strings in resulting array
['rgb(0,0,0)', ...,'rgb(0,255,0)', ...'rgb(255,255,255)']

CSS RGB hexadecimal notation RRGGBB

// RGB hexadecimal notation as strings in resulting array
['#000000', ...,'#00ff00', ...'#ffffff']

Winning criteria

Least bytes used to write the program.

  • Comments are not for extended discussion; this conversation has been moved to chat. – Mego Sep 29 at 13:53

33 Answers 33

R, 25 bytes


Try it online!

  • Not familiar with R, but does this fail to output #000000? – jimbo1qaz Sep 25 at 1:27
  • 2
    No, it outputs #000000. See the TIO link – J.Doe Sep 25 at 1:53
  • @jimbo1qaz a:b-c makes a vector from a-c to b-c, inclusive (it makes a vector from a to b, then subtracts c from each entry). – Arthur Sep 25 at 8:04
  • 2
    Ahh, so R specifies colons with tighter precedence than arithmetic... Unlike Python slices. – jimbo1qaz Sep 25 at 8:05

Python 2, 77 40 39 37 bytes

print['#%06X'%c for c in range(8**8)]

Try it online!

-1 byte thanks to Digital Trauma

-2 bytes thanks to dylnan

  • 2
    Why do you need the lambda? The list comprehension itself is a valid answer, isn't it? – Adirio Sep 24 at 14:42
  • 2
    Try 8**8 instead of 1<<24 to save a byte – Digital Trauma Sep 24 at 17:17
  • 2
    how about print['... – dylnan Sep 24 at 22:49
  • 1
    @Adirio A value alone does not count as an implementation of a challenge. – Jonathan Frech Sep 25 at 1:59
  • 2
    @Adirio You yourself wrote [...] in a Python terminal [...] -- thus your submission would be written in Python 2 REPL, not Python 2. – Jonathan Frech Sep 26 at 14:18

PowerShell, 28 26 bytes


Try it online!

Loops from 1 to 16mb (16777216). Each iteration, we use the -format operator acting on the current number pre-decremented --$_ against the string "#{0:x6}". Here, we're specifying hex values, padded to 6 digits, with a hash # in front. On TIO, limited to 60 seconds / 128KiB of output. Change the 1 to (16mb-5) to see how it ends.

JavaScript (ES7), 65 62 61 bytes

Saved 3 4 bytes thanks to @tsh

Returns an array of #RRGGBB strings.


Try it online! (truncated output)

  • Current Python solution use 8**8 instead of 1<<24. It would work on JS too. – tsh Sep 26 at 9:27

Common Lisp, 42 bytes

(dotimes(i 16777216)(format t"#~6,'0x "i))

Try it online!

  • 1
    May be the first format-golf I've seen. +1 on that basis alone. – Silvio Mayolo Sep 25 at 2:08

Japt, 14 bytes

Outputs as #rrggbb.

G²³ÇsG ùT6 i'#

Try it (Limited to the first 4096 elements)


G                  :16
 ²                 :Squared
  ³                :Cubed
   Ç               :Map the range [0,result)
    sG             :  Convert to base-16 string
       ù           :  Left pad
        T          :   With 0
         6         :   To length 6
           i'#     :  Prepend "#"
  • Interesting language. Any idea why the letter T is used for "0"? I get 16 -> G to save a byte, but T -> 0 doesn't accomplish the same. – Alec Sep 24 at 20:15
  • @Alec Because if you replace T with 0, it joins with the 6 and becomes 06. – geokavel Sep 25 at 4:54
  • Ah, gotcha. So is there one letter per digit for cases where you don't want it to join with the previous/next digit? – Alec Sep 25 at 6:57
  • @Alec, as geokavel said, in this particular case, it saves me a byte in having to use a comma to delimit the 2 arguments being passed to ù. Another typical use case for it is to use it as a counter when you need to increment a variable while, for example, mapping over an array. And, of course, as it's a variable, you can simply assign a value to it too, if needed. 0 is the only single digit integer that has it's own variable, though - well, technically, 7 as the 6 input variable U-Z default to 0. The other integers assigned to variables in Japt are: -1, 10-16, 32, 64 & 100. – Shaggy Sep 25 at 9:26
  • If you'd like to learn more about Japt, feel free to ping me in our chatroom. – Shaggy Sep 25 at 9:27

Haskell, 41 bytes

mapM id$"#":(['0'..'9']++l<$l)

Try it online!

05AB1E, 15 14 10 bytes


Try it online.


15Ý           # Create a list in the range [0, 15]
   h          # Convert each to a hexadecimal value
    6ã        # Create each possible sextuple combination of the list
      J       # Join them together to a single string
       '#ì    # And prepend a "#" before each of them

Batch, 87 bytes

@set s= in (0,1,255)do @
@for /l %%r%s%for /l %%g%s%for /l %%b%s%echo rgb(%%r,%%g,%%b)

Outputs in CSS format. The variable substitution happens before the for statement is parsed so the the actual code is as follows:

@for /l %%r in (0,1,255)do @for /l %%g in (0,1,255)do @for /l %%b in (0,1,255)do @echo rgb(%%r,%%g,%%b)

C# (Visual C# Interactive Compiler), 47 bytes


Try it online!

C# (.NET Core), 75 bytes

()=>{int i=1<<24;var a=new string[i];for(;i-->0;)a[i]=$"#{i:X6}";return a;}

Try it online!

Port of JAVA 10 version with C# interpolated string format

K (oK), 19 bytes



Try it online! (limited to first 500 numbers)


Dump out rgb strings. Convert each number between 0 and 16777216 to base 256, then convert to strings...

$(3#256)\'!16777216 / the solution
          !16777216 / range 0..16777215
 (     )\'          / split each both
  3#256             / 256 256 256
$                   / string

MATL, 17 15 bytes


Try it online!

The TIO version displays the first 2^10 only as not to time out. I included the final iteration in the footer to show that it indeed terminates at #FFFFFF. Saved one byte by changing to fprintf instead of manually assembling the string. Outputs a comma-separated list.


24W:q            % Range from 0 to 2^24-1
     '#%06X,'    % fprintf format spec (# followed by hexadecimal, zero-padded, fixed-width, followed by newline)
             YD  % Call fprintf. Internally loops over range.

APL (Dyalog Unicode), 47 43 20 bytes


Try it online!

Given enough time/memory, this anonymous function will output all \$2^{24}-1\$ color codes. To see this, you can swap the 6⍴ for a 4⍴ in the code, and you'll see it output every code with up to 4 digits.

Thanks to @Dzaima and @ngn for the 23 bytes.

Uses ⎕IO←0.


'#',(⎕D,⎕A)[↑,⍳6⍴16] ⍝ Main function
               ⍳6⍴16  ⍝ Generate every possible 6 digit hex number in a matrix format
              ,       ⍝ Ravel the matrix (from a 16x16x16x16x16x16 matrix to a 16^6x2 list)
             ↑        ⍝ Mix; (turns the list into a 16^6x2 matrix)
    (⎕D,⎕A)[       ] ⍝ Use that matrix to index the vector of the digits 0-9 concatenated with the alphabet.
'#',                  ⍝ Then prepend a '#' to each.

Ruby, 31 bytes


Try it online!

  • I’m kind of amazed % takes a string that long and an array that long. FYI you can save a byte by using a literal line break instead of \n. – Jordan Sep 27 at 1:23

V, 25 bytes


Try it online! (replaced 16777215 by 31)


8É0                                " insert 8 zeroes
   0l                              " move cursor to the second character
     rx                            " replace by x
       16777215ñ      ñ            " 16777215 times do ..
                Ä                  " .. duplicate line
                 <C-a>             " .. increment (leading 0x makes sure it uses hexadecimals)
                       0<C-v>      " move cursor to beginning of line and start selection
                             Gl    " select the column with 0x
                               s#  " replace by #

Batch, 69 + 4 = 73

g.cmd, 69

for /L %%A in (0,1,16777215)do cmd/kexit %%A&set #%%A=#!=exitcode:~2!

Saves the hexadecimal value with form #RRGGBB into an 'Array'.

g.cmd is to be called using cmd /V/Q/K g.cmd. This is where the + 4 comes from, /V/Q, counting as 4 additional characters compared to just cmd /K g.cmd. This sets up an environment that has the 'Array' in memory. It also takes forever to run, so use very low values to try or break execution using Ctrl+C



  • /V enables delayed expansion, but is shorter than setlocal EnableDelayedExpansion, which is why we need the cmd call in the first place
  • /Q omits the output and is equivalent to @echo off
  • /K lets you execute an expression (In this case g.cmd) and does not exit afterwards, so you can check the 'Array' by using set #


for /L %%A IN (0,1,16777215) DO (
    cmd /k exit %%A
    set #%%A=#!=exitcode:~2!

This bit uses a trick documented here to convert a normal number to a hexadecimal, then saves that value into an 'Array'.

I've been calling that storing structure an 'Array' but that is not actually right as true Arrays do not exist in Batch. BUT you can name variables so that they have arraylike names, like so:

set elem[1]=First element
set elem[2]=Second one

or, like in this case:

set #1=First element
set #2=Second one

You can still access them via !#%position%!

  • I'm not sure. But maybe /V/Q/K may be claimed as "arguments" for interpreter and count as "3 + 69 = 72". meta – tsh Sep 26 at 9:38
  • I didn't know that and will update my answer accordingly. Thx @tsh – Grub4K Sep 26 at 20:11

Groovy, 53 bytes

c={a=[];(1<<24).times{a.add "".format("#%06x",it)};a}

Function definition. c() returns an ArrayList (I assume that's fine, even through the question asks for an array).

Ungolfed, with implicit types:

ArrayList<String> c = {
    ArrayList<String> a = []
    (1 << 24).times { 
        a.add("".format("#%06x", it)) // add the hex-formatted number to the list.
    return a

Try it online!

Java 10, 87 84 bytes

v->{int i=1<<24;var r=new String[i];for(;i-->0;)r[i]="".format("#%06X",i);return r;}

-3 bytes thanks to @archangel.mjj.

Try it online (limited to the first 4,096 items).


v->{                       // Method with empty unused parameter & String-array return-type
  int i=1<<24;             //  Integer `i`, starting at 16,777,216
  var r=new String[i];     //  Result String-array of that size
  for(;i-->0;)             //  Loop `i` in the range (16777216, 0]
    r[i]=                  //   Set the `i`'th item in the array to:
      "".format("#%06X",i);//   `i` converted to a hexadecimal value (of size 6)
  return r;}               //  Return the result-array
  • Ah, you posted this while I was writing my post, so we have very similar answers. You can improve by three bytes with r[i]="".format("#%06X",i); – archangel.mjj Sep 24 at 10:17
  • @archangel.mjj Ah, I'm an idiot. Thanks! I actually had "".format("#%06X",i) before since I saw it in the Python answer, but I dropped the answer because I couldn't get it to work fast enough for TIO. Then I saw everyone just outputting the first 4,096 items on TIO, so I wrote the answer again, forgetting about "#%06X"... >.< – Kevin Cruijssen Sep 24 at 10:27
  • @KevinCruijssen I never knew you could do var r in Java.. – FireCubez Sep 24 at 18:12
  • @FireCubez It's new since Java 10. :) Here a relevant tip to see what is and isn't possible with var in Java. – Kevin Cruijssen Sep 24 at 20:52

PHP, 68 62 bytes

This is supposed to be placed inside a file, the array is returned in the end, to be usable.


To have access to the array, simply give the result of the include (e.g.: $a = include 'xyz.php';) to a variable.

Thanks to @manatwork for saving me 6 bytes and fix a goof.

  • 1
    Are you sure this will ever output hex digits with the %1$06d format string? And I see no reason for using 1$. You could reduce the length by including the “#” in the format string: #%06x. Which would come handy when adding extra characters to fix the range, as currently counts up to 16777216 = #1000000. – manatwork Sep 24 at 15:27
  • Well, it would .... If I didn't forgot to change %d to %x. And completely forgot about moving the # inside the sprintf() call. You saved me 6 bytes. Thank you – Ismael Miguel Sep 24 at 16:45

MATL, 11 bytes


Try it online! (with only three hex digits instead of six)


'#'   % Push this character
5Y2   % Push '01234567890ABCDEF'
6     % Push 6
Z^    % Cartesian power. Gives a (16^6)×6 char matrix
Yc    % String concatenation. '#' is implicitly replicated
      % Implicitly display

Bash + jot, 22

jot -w\#%06X $[8**8] 0

Try it online!

Perl 5, 31 bytes

",$_ for 0..8**8-1

Try it online!

Lua, 47 45 bytes

for i=1,8^8 do s='#%06X'print(s:format(i))end

Try it online!

  • 1
    You could toss your variable s and save a byte. – Jonathan Frech Sep 24 at 21:51

T-SQL, 122 117 bytes

Returns a 16,777,216-row table of #RRGGBB strings. The line break is for readability only:

SELECT'#'+FORMAT(n,'X6')FROM t option(maxrecursion 0)

Uses a recursive CTE for a number table from 0 to 2^24-1, then uses the built-in FORMAT command (available in SQL 2012 or later) to turn it into a 6-digit hex string. Attach the # to the front, and we're done.

Edit 1: Removed POWER() function, the number was shorter :P

Jelly, 12 bytes


Try it online!

Jelly, 8 bytes


Try it online! (note: uses 2 rather than 6 as 6 times out on TIO)

Function submission (because Jelly full programs will, by default, print lists of strings with no delimiters between them, making it hard to see the boundaries). The TIO link contains a wrapper to print a list of strings using newlines to separate them.


ØH         All hex digits (“0123456789ABCDEF”)
  ṗ6       Find all strings of 6 of them (order relevant, repeats allowed)
    ”#;    Prepend “#”
       Ɱ     to each of the resulting strings
  • 1
    Out of interest -- why did you make your answer a community wiki? – Jonathan Frech Sep 25 at 1:53
  • @JonathanFrech: I do this for all my posts because a) it reduces the incentive for people to game the reputation system (as the post doesn't give reputation), b) I'm happy to have my posts edited and the community-wiki marker is a way to indicate that. Stack Exchange's reputation system is more or less completely broken: on a past account, I once intentionally rep-capped every day for a week to show how easy the system was to game. Nowadays I pretty much want no part in it, especially as higher reputation simply just makes the site try to persuade you to moderate it. – ais523 Sep 25 at 2:19
  • Just curious -- on which stack did you achieve to game the reputation system? – Jonathan Frech Sep 25 at 2:49
  • @JonathanFrech: This one. I was a 20k user, but eventually deleted my account because it was kind-of messing up my life, and because the reputation system was actively pushing me into making content that made the site worse, as opposed to better. – ais523 Sep 25 at 2:52

PHP, 43 bytes

<?php for(;$i<1<<24;printf("#%06X ",$i++));

Try it online!

  • 1<<24 --> 8**8 should work here to, credits to @DigitalTrauma – Adirio Sep 25 at 7:33

Scala, 40 bytes

(1 to 1<<24).map(x=>println(f"#$x%06x"))

Try it online!

Perl 6, 26 bytes

{map *.fmt("#%06X"),^8**8}

Try it online!

Uses the same format as everyone else. Times out on TIO.

Or, in rgb format:

31 bytes

{map {"rgb($_)"},[X] ^256 xx 3}

Try it online!

  • I think the rgb output should be rgb(0, 0, 0) including the string rgb. – nwellnhof Sep 25 at 13:07
  • @nwellnhof Updated (though it ended up shorter to do hexadecimal) – Jo King Sep 26 at 1:26

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.