{"id":29614906,"url":"https://github.com/myfreeweb/httpotion","last_synced_at":"2025-07-21T00:01:48.861Z","repository":{"id":4407517,"uuid":"5544923","full_name":"valpackett/httpotion","owner":"valpackett","description":"[Deprecated because ibrowse is not maintained] HTTP client for Elixir (use Tesla please)","archived":false,"fork":false,"pushed_at":"2022-08-02T13:03:16.000Z","size":221,"stargazers_count":723,"open_issues_count":7,"forks_count":100,"subscribers_count":16,"default_branch":"trunk","last_synced_at":"2025-07-19T03:14:46.835Z","etag":null,"topics":["client","elixir","http","ibrowse","rest"],"latest_commit_sha":null,"homepage":"https://hexdocs.pm/httpotion/readme.html","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/valpackett.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-08-24T19:37:32.000Z","updated_at":"2025-06-19T19:41:04.000Z","dependencies_parsed_at":"2022-09-20T23:02:40.551Z","dependency_job_id":null,"html_url":"https://github.com/valpackett/httpotion","commit_stats":null,"previous_names":["unrelentingtech/httpotion","myfreeweb/httpotion"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/valpackett/httpotion","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valpackett%2Fhttpotion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valpackett%2Fhttpotion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valpackett%2Fhttpotion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valpackett%2Fhttpotion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valpackett","download_url":"https://codeload.github.com/valpackett/httpotion/tar.gz/refs/heads/trunk","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valpackett%2Fhttpotion/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266217170,"owners_count":23894242,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["client","elixir","http","ibrowse","rest"],"created_at":"2025-07-21T00:01:21.780Z","updated_at":"2025-07-21T00:01:48.838Z","avatar_url":"https://github.com/valpackett.png","language":"Elixir","readme":"[![hex.pm version](https://img.shields.io/hexpm/v/httpotion.svg?style=flat)](https://hex.pm/packages/httpotion)\n[![hex.pm downloads](https://img.shields.io/hexpm/dt/httpotion.svg?style=flat)](https://hex.pm/packages/httpotion)\n[![API Docs](https://img.shields.io/badge/api-docs-yellow.svg?style=flat)](https://hexdocs.pm/httpotion/)\n[![unlicense](https://img.shields.io/badge/un-license-green.svg?style=flat)](http://unlicense.org)\n\n# HTTPotion\n\nHTTP client for [Elixir], based on [ibrowse].\nContinues the HTTPun tradition of [HTTParty], [HTTPretty], [HTTParrot] and [HTTPie].\n\n*Note*: unfortunately, ibrowse seems a bit buggy and not super actively maintained. You might want to check out [Tesla](https://github.com/teamon/tesla) with hackney instead, and [this](https://github.com/teamon/tesla/issues/293#issuecomment-522312859) cert verification setup.\n\n## Installation\n\nAdd HTTPotion to your project's dependencies in `mix.exs`:\n\n```elixir\n  defp deps do\n    [\n      {:httpotion, \"~\u003e 3.1.0\"}\n    ]\n  end\n\n  def application do\n    [ applications: [:httpotion] ]\n    # Application dependency auto-starts it, otherwise: HTTPotion.start\n  end\n```\n\nAnd fetch your project's dependencies:\n\n```bash\n$ mix deps.get\n```\n\n## Usage\n\n*Note*: You can load HTTPotion into the Elixir REPL by executing this command from the root of your project:\n\n```\n$ iex -S mix\n```\n\n*Note*: HTTPotion now enables certificate verification by default, using a few default CA bundle paths (`/etc/ssl/cert.pem` etc.) or the [certifi](https://hex.pm/packages/certifi) package (which is not a mandatory dependency).\n\nSome basic examples:\n\n```elixir\niex\u003e response = HTTPotion.get \"https://httpbin.org/get\"\n%HTTPotion.Response{\n  body: \"{\\n…\",\n  headers: %HTTPotion.Headers{ hdrs: %{\"connection\" =\u003e \"keep-alive\", …} },\n  status_code: 200\n}\n\niex\u003e HTTPotion.Response.success?(response)\ntrue\n\n# Response headers are wrapped to allow case-insensitive access (and to support both atoms and strings)\niex\u003e response.headers[:sErvEr]\n\"meinheld/0.6.1\"\n\niex\u003e response.headers[\"ConTenT-TyPe\"]\n\"application/json\"\n\n# Response headers can have multiple values\niex\u003e response = HTTPotion.get \"https://httpbin.org/response-headers?foo=1\u0026foo=2\u0026bar=1\"\n%HTTPotion.Response{\n  body: \"{\\n…\",\n  headers: %HTTPotion.Headers{ hdrs: %{\"foo\" =\u003e [\"1\", \"2\"], \"bar\" =\u003e \"1\" …} },\n  status_code: 200\n}\n\n# You can provide a map for the query string\niex\u003e HTTPotion.get(\"https://httpbin.org/get\", query: %{page: 2})\n%HTTPotion.Response{body: \"…\", headers: …, status_code: 200}\n\n# Follow redirects\niex\u003e HTTPotion.get(\"https://httpbin.org/redirect-to?url=http%3A%2F%2Fexample.com%2F\", follow_redirects: true)\n%HTTPotion.Response{body: \"…\u003ctitle\u003eExample Domain\u003c/title\u003e…\", headers: …, status_code: 200}\n\n# Send form data\niex\u003e HTTPotion.post \"https://httpbin.org/post\", [body: \"hello=\" \u003c\u003e URI.encode_www_form(\"w o r l d !!\"),\n  headers: [\"User-Agent\": \"My App\", \"Content-Type\": \"application/x-www-form-urlencoded\"]]\n%HTTPotion.Response{body: \"…\", headers: …, status_code: 200}\n\n# Use a custom method\niex\u003e HTTPotion.request :propfind, \"http://httpbin.org/post\", [body: \"I have no idea what I'm doing\"]\n%HTTPotion.Response{body: \"…\", headers: …, status_code: 405}\n\n# Send Basic auth credentials\niex\u003e HTTPotion.get \"https://httpbin.org/basic-auth/foo/bar\", [basic_auth: {\"foo\", \"bar\"}]\n%HTTPotion.Response{\n  body: \"…\",\n  headers: %HTTPotion.Headers { hdrs: %{\"Access-Control-Allow-Credentials\": \"true\", …} },\n  status_code: 200\n}\n\n# Pass options to ibrowse (note that it usually takes char_lists, not elixir strings)\niex\u003e HTTPotion.get \"https://check-tls.akamaized.net\", [ ibrowse: [ ssl_options: [ versions, [:'tlsv1.1'] ] ] ]\n%HTTPotion.Response{body: \"…TLS SNI: present - Check TLS - (https,tls1.1,ipv4)…\", headers: …, status_code: 200}\n\n# Change the timeout (default is 5000 ms)\niex\u003e HTTPotion.get \"https://example.com\", [timeout: 10_000]\n\n# If there is an error a `HTTPotion.ErrorResponse` is returned\niex\u003e HTTPotion.get \"http://localhost:1\"\n%HTTPotion.ErrorResponse{message: \"econnrefused\"}\n\n# You can also raise `HTTPError` with the `bang` version of request\niex\u003e HTTPotion.get! \"http://localhost:1\"\n** (HTTPotion.HTTPError) econnrefused\n```\n\nThe `Response` is [a struct](https://elixir-lang.org/getting-started/structs.html), you can access its fields like: `response.body`.\n\n`response.headers` is a struct (`HTTPotion.Headers`) that wraps a map to provide case-insensitive access (so you can use `response.headers[:authorization]` and it doesn't matter if the server returned `AuThOrIZatIOn` or something).\n\n`HTTPError` is [an exception](https://elixir-lang.org/getting-started/try-catch-and-rescue.html) that happens when a bang request (`request!` / `get!` / …) fails.\n\nAvailable options and their default values:\n\n```elixir\n{\n  body: \"\",                # Request's body contents, e.g. \"{json: \\\"string\\\"}\"\n  headers: [],             # Request's headers, e.g. [Accept: \"application/json\"]\n  query: nil,              # Query string, e.g. %{page: 1}\n  timeout: 5000,           # Timeout in milliseconds, e.g. 5000\n  basic_auth: nil,         # Basic auth credentials, e.g. {\"username\", \"password\"}\n  stream_to: nil,          # A process to stream the response to when performing async requests\n  direct: nil,             # An ibrowse worker for direct mode\n  ibrowse: [],             # ibrowse options\n  auto_sni: true,          # Whether TLS SNI should be automatically configured (does URI parsing)\n  follow_redirects: false, # Whether redirects should be followed\n}\n\n```\n\n### Metaprogramming magic\n\nYou can extend `HTTPotion.Base` to make cool HTTP API wrappers (this example uses [Poison] for JSON):\n\n```elixir\ndefmodule GitHub do\n  use HTTPotion.Base\n\n  def process_url(url) do\n    \"https://api.github.com/\" \u003c\u003e url\n  end\n\n  def process_request_headers(headers) do\n    Dict.put headers, :\"User-Agent\", \"github-potion\"\n  end\n\n  def process_response_body(body) do\n    body |\u003e Poison.decode!\n  end\nend\n```\n\n```elixir\niex\u003e GitHub.get(\"users/unrelentingtech\").body[\"public_repos\"]\n233\n```\n\nRead the source to see all the hooks.\n\nKeep in mind that `process_response_body` and `process_response_chunk` get iodata.\nBy default, they call `IO.iodata_to_binary`.\nBut efficient parsers like Poison can work directly on iodata.\n\n### Asynchronous requests\n\nYou can get the response streamed to your current process asynchronously:\n\n```elixir\niex\u003e HTTPotion.get \"http://httpbin.org/get\", [stream_to: self]\n%HTTPotion.AsyncResponse{id: -576460752303419903}\n\niex\u003e flush\n%HTTPotion.AsyncHeaders{\n  id: -576460752303419903,\n  status_code: 200,\n  headers: %HTTPotion.Headers{ hdrs: %{\"connection\" =\u003e \"keep-alive\", …} }\n}\n%HTTPotion.AsyncChunk{\n  id: -576460752303419903,\n  chunk: \"{\\n…\"\n}\n%HTTPotion.AsyncEnd{\n  id: -576460752303419903\n}\n```\n\nNote that instead of `process_response_body`, `process_response_chunk` is called on the chunks before sending them out to the receiver (the `stream_to` process).\n\n### Direct access to ibrowse workers\n\nibrowse allows you to use its separate worker processes directly.\nWe expose this functionality through the `direct` option.\n\nDon't forget that you have to pass the URL to the worker process, which means the worker only communicates with one server (domain!)\n\n```elixir\niex\u003e {:ok, worker_pid} = HTTPotion.spawn_worker_process(\"http://httpbin.org\")\n\niex\u003e HTTPotion.get \"httpbin.org/get\", [direct: worker_pid]\n%HTTPotion.Response{body: \"…\", headers: [\"Connection\": \"close\", …], status_code: 200}\n```\n\nYou can even combine it with async!\n\n```elixir\niex\u003e {:ok, worker_pid} = HTTPotion.spawn_worker_process(\"http://httpbin.org\")\n\niex\u003e HTTPotion.post \"httpbin.org/post\", [direct: worker_pid, stream_to: self, headers: [\"User-Agent\": \"hello it's me\"]]\n%HTTPotion.AsyncResponse{id: {1372,8757,656584}}\n```\n\n### Type analysis\n\nHTTPotion contains [typespecs] so your usage can be checked with [dialyzer], probably via [dialyxir] or [elixir-ls].\n\nHTTPotion's tests are checked with dialyxir.\n\n[Elixir]: https://elixir-lang.org\n[ibrowse]: https://github.com/cmullaparthi/ibrowse\n[HTTParty]: https://github.com/jnunemaker/httparty\n[HTTPretty]: https://github.com/gabrielfalcao/HTTPretty\n[HTTParrot]: https://github.com/edgurgel/httparrot\n[HTTPie]: https://github.com/jkbr/httpie\n[Poison]: https://github.com/devinus/poison\n[typespecs]: https://elixir-lang.org/getting-started/typespecs-and-behaviours.html\n[dialyzer]: http://erlang.org/doc/man/dialyzer.html\n[dialyxir]: https://github.com/jeremyjh/dialyxir\n[elixir-ls]: https://github.com/JakeBecker/elixir-ls\n\n## Contributing\n\nPlease feel free to submit pull requests!\n\nBy participating in this project you agree to follow the [Contributor Code of Conduct](https://www.contributor-covenant.org/version/1/4/).\n\n## License\n\nThis is free and unencumbered software released into the public domain.  \nFor more information, please refer to the `UNLICENSE` file or [unlicense.org](https://unlicense.org).\n","funding_links":[],"categories":["HTTP","Elixir","Uncategorized"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmyfreeweb%2Fhttpotion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmyfreeweb%2Fhttpotion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmyfreeweb%2Fhttpotion/lists"}