Link Search Menu Expand Document

Elixir: HTML/CSS to Image

Generate Images and PDFs with Elixir. Renders exactly like Google Chrome.

Render PNG, JPG, or WebP images + PDFs with Elixir from HTML/CSS or reusable dynamic templates.

Live demo Get an API Key


Generating images with Elixir

  1. The API takes your HTML/CSS and runs it inside a real instance of Google Chrome to convert your HTML into an image.
  2. Use Elixir to send the API your HTML/CSS.
  3. You’ll get back JSON with the URL to your generated image.

For more details on how this works, see Creating an image.

Example API response:

{
  "url": "https://hcti.io/v1/image/be4c5118-fe19-462b-a49e-48cf72697a9d",
  "id": "be4c5118-fe19-462b-a49e-48cf72697a9d"
}

Image generated with Elixir. Convert HTML to an image using Elixir.

Authentication with Elixir

The API uses HTTP Basic authentication.

Your username is your User ID and your password is your API Key. Both of these are available from the dashboard. The Elixir code sample demonstrates how to authenticate your request.

You can sign up for a free API key to get started.

Free API Key for Elixir


Elixir example code

This Elixir code example sends an HTTP POST to the https://hcti.io/v1/image API to convert your HTML/CSS to an image.

This example sends JSON using Jason for encoding and Erlang/OTP’s built-in :httpc client for the HTTP request.

Add Jason to your mix.exs dependencies:

defp deps do
  [
    {:jason, "~> 1.4"}
  ]
end
:inets.start()
:ssl.start()

user_id = "your-user-id"
api_key = "your-api-key"

payload = %{
  html: "<div class='box'>Elixir ✅</div>",
  css: ".box { border: 4px solid #03B875; padding: 20px; font-family: Roboto, sans-serif; }",
  google_fonts: "Roboto"
}

body = Jason.encode!(payload)

auth = Base.encode64("#{user_id}:#{api_key}")

headers = [
  {'authorization', String.to_charlist("Basic #{auth}")},
  {'accept', 'application/json'}
]

request = {
  'https://hcti.io/v1/image',
  headers,
  'application/json',
  String.to_charlist(body)
}

case :httpc.request(:post, request, [], []) do
  {:ok, {{_, status, _}, _headers, response_body}} when status in 200..299 ->
    IO.puts(response_body)

  {:ok, {{_, status, _}, _headers, response_body}} ->
    raise "Request failed with status #{status}: #{to_string(response_body)}"

  {:error, reason} ->
    raise "Request failed: #{inspect(reason)}"
end

# {"url":"https://hcti.io/v1/image/1113184e-419f-49f1-b231-2069942a186f"}

Phoenix example with Req

For Phoenix applications, Req is a popular HTTP client that keeps the request code compact and uses Jason for JSON encoding.

Add Req and Jason to your mix.exs dependencies:

defp deps do
  [
    {:jason, "~> 1.4"},
    {:req, "~> 0.5"}
  ]
end

Store your credentials in config or environment variables, then call the API from a context or service module.

defmodule MyApp.Images.HtmlCssToImage do
  @endpoint "https://hcti.io/v1/image"

  def create_image do
    user_id = System.fetch_env!("HCTI_USER_ID")
    api_key = System.fetch_env!("HCTI_API_KEY")

    payload = %{
      html: "<div class='box'>Phoenix ✅</div>",
      css: ".box { border: 4px solid #03B875; padding: 20px; font-family: Roboto, sans-serif; }",
      google_fonts: "Roboto"
    }

    case Req.post(@endpoint, auth: {:basic, "#{user_id}:#{api_key}"}, json: payload) do
      {:ok, %{status: status, body: %{"url" => url}}} when status in 200..299 ->
        {:ok, url}

      {:ok, %{status: status, body: body}} ->
        {:error, {status, body}}

      {:error, reason} ->
        {:error, reason}
    end
  end
end

Need help?

Talk to a human. Please email us support@htmlcsstoimage.com with any questions and we’ll gladly help you get started.


Back to top

Built with extensive integration tests and serious care for developer happiness.
© 2018-2026 Code Happy, LLC.

Page last modified: Jul 3 2026 at 01:46 PM.

Edit this page on GitHub.