Making HTTP Requests in Solidity
HTTP requests work on Ethereum and in Solidity with what’s known as oracles

Making HTTP requests in Solidity is simple with Chainlink. If you’d like more insight on best practices, then after reading this article be sure to read API calls on Blockchain.
Let’s take a step back to start.
How Does Making a Chainlink Request Work?
Remember that Chainlink oracles are blockchain middleware, so we need something to programmatically tell them to make an HTTP request. We need something to initiate them to start getting data for us. These instructions for telling a chainlink node to start getting data are called Chainlink Initiators.
A Chainlink node can have as many initiators as it likes. Each will define a different way for the node to start getting data.
Initiator 1: Start getting data when x occurs
Initiator 2: Start getting data when y occurs
Initiator 3: Start getting data when z occurs
Etc…
Along with the initiators, as well as a set of instructions for what to do when they are initiated. This set of instructions about what to do are called the “tasks” or “adapters” list.
Adapter 1: Do q to data once received
Adapter 2: Do r to data once received
Adapter 3: Do s to data once received
Etc…
The combination of initiators and adapters makes up a single job on a chainlink node. Chainlink nodes can have multiple jobs defined so that they can do many different things in a simple interface.
Here is what a sample job definition looks like, you can see it has a list of initiators
defined at the top, and then a list of adapters
/tasks
defined after. You can also see, that the initiators can take parameters to allow them to do even more. This sample job definition is known as a jobspec
.
{
"initiators": [
{
"type": "runlog",
"params": {
"address": "0xd8c819674b79c7372d56db03280a5695a9254894"
}
}
],
"tasks": [
{
"type": "httpget"
},
{
"type": "jsonparse"
},
{
"type": "multiply"
},
{
"type": "ethuint256"
},
{
"type": "ethtx"
}
]
}
Most nodes have a lot of similar jobs, and the one in the sample above is one of the most common jobs out there. This jobspec defines how to make simple httpget
requests into your smart contract. There is also an httppost
adapter if you’d like to make a POST request instead of a GET. This job is defined by a:
- Runlog initiator
- This specific list of adapters/tasks: httpget, jsonparse, multiply, ethuint256, and ethTx adapters.
The Runlog initiator is one of the most common initiators used. It defines that the chainlink node will watch the blockchain for any log events that include that job’s ID. Once it finds an event, it will execute the adapters, and post the data on-chain. We will go over what each one of these adapters does soon.
Your smart contract will have to wait a little for the Chainlink node to return your data, but once it does, your smart contract will pull the data from this transaction.

What Does This Look Like in Solidity?
To show what this looks like in code, let’s look at getting the numerical price of ETH. You can use this Remix link to follow along, but here is a subset of that contract code.
// Creates a Chainlink request with the uint256 multiplier job
// Ideally, you'd want to pass the oracle payment, address, and jobID as
function requestEthereumPrice()
public
onlyOwner
{
// newRequest takes a JobID, a callback address, and callback function as input
Chainlink.Request memory req = buildChainlinkRequest(JOBID, address(this), this.fulfill.selector);
req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
req.add("path", "USD");
req.addInt("times", 100);
sendChainlinkRequestTo(ORACLE_ADDRESS, req, ORACLE_PAYMENT);
}// fulfill receives a uint256 data type
function fulfill(bytes32 _requestId, uint256 _price)
public
// Use recordChainlinkFulfillment to ensure only the requesting oracle can fulfill
recordChainlinkFulfillment(_requestId)
{
currentPrice = _price;
}
To start making a request to a chainlink node, we call the buildChainlinkRequest
function that is imported from the ChainlinkClient.sol
, this function returns a Chainlink.Request
struct. In this function, we pass the jobID, return address, and fulfillment function when we start to build it.
We can find a jobID of an independent Chainlink node by heading over to a node listing service, like market.link, and searching for what we want. Node listing services are where independent nodes post their information about how to connect to their Chainlink node. You can use them to build your network of decentralized oracles. Make sure you’re on the correct network (ropsten, mainnet, kovan, etc).
For this, we want a job that can make an httpget
call and return a uint256
, so let’s try searching for that job on the ropsten network.

Let’s pick a job, and just make sure that the jobspec
is what we are looking for. We can head on over to the jobspec
tab to see what the initiators and adapters are.

To make sure this job has the right adapters, we can check out their tasks/adapters list. The image above shows that this job has exactly the initiators and adapters/tasks that we want.
Once we verify that the job has the adapters we want, we can then copy the job ID to use in our code. You can see other nodes that have a similar job, and you’ll need this list when you make your contract decentralized, but again for testing and developing we can just pull from a single node. Make sure you also grab the oracle address, as you’ll need this later.
Chainlink.Request memory req = buildChainlinkRequest(JOBID, address(this), this.fulfill.selector);
We then put the JOBID in the first parameter of our buildChainlinkReqeust
. The second parameter is the address of the contract to return the data to also known as the callbackaddress
. The last parameter is the function that will process the data once collected aka thecallbackFunctionSignature
. We want to return the data to this contract, so we put in address(this)
, and our function that will be processing the data will be fulfill
. We defined the fulfill function right below this one.
function fulfill(bytes32 _requestId, uint256 _price)
public
// Use recordChainlinkFulfillment to ensure only the requesting oracle can fulfill
recordChainlinkFulfillment(_requestId)
{
currentPrice = _price;
}
The uint256 _price
parameter is where the Chainlink node will input the price gathered from making the http get request. In our example above, we are just setting the return value from the node to our currentPrice
variable.
Back in the requestEthereumPrice
function, we can then add parameters to our adatpers/tasks. Let’s go over what each adapter does:
httpget
The Chainlink node will make an HTTP GET request; usually, this is a simple API call.
The HTTP GET request that we want to make in the parameters passed to the req
variable.
req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
At the time of writing, the return value of this HTTP GET request is:
{"USD":391.41}
jsonparse
Once the node makes the HTTP GET request, it will go through the json and find only the value that we want. Storing the entire return of the HTTP GET request would be really expensive, as the more you store on the Ethereum chain the more ETH gas you have to pay. So, we want to return as little as possible.
req.add("path", "USD");
This will condense the return of the HTTP GET request to just the value391.41
. It walks down the json of the {“USD”:391.41}
return value. For longer json returns, you can add indexes of lists too. For example, if you had an object like:
{"USD": [ "price": {"ETH": 391.41}]}
We could walk down the path to that value with:
req.add("path", "USD.0.ETH");
multiply/times
Once we get the 391.41
value, we have to make it a whole number. Decimals don’t work in solidity, and we need to represent decimals using fixed-point math.
req.addInt("times", 100);
This will adapt our result once more to be 39141
(since we move the decimal place over twice by multiplying by 100).
ethuint256
You’ll notice in our code above, we don’t pass any parameters to this adapter; that’s because we don’t need to. This adapter just converts our answer of 39141
to the solidity understandable format.
ethtx
This one also doesn’t need any parameters. This is the adapter that actually posts the data back on-chain.
Now we use the sendChainlinkRequestTo
method, with the address of the oracle we got from market.link, the request itself, and the oracle_payment.
sendChainlinkRequestTo(ORACLE_ADDRESS, req, ORACLE_PAYMENT);
We get the ORACLE_ADDRESS
and ORACLE_PAYMENT
from market.link as well. The Oracle payment is how much LINK oracle gas we want to send the oracle, each job has its own minimum cost to send.
Send It
Now, let’s run it again! Let’s deploy the contract, fund it with link, and then request the price of ETH. You can go through the example walkthrough if you’re confused about how to do this. Or the more step-by-step YouTube video:
The Chainlink node will pick up on the request by reading it off the blockchain. Again, it can read it off the blockchain because it is using the Runlog initiator. Once it picks up the job, it runs through the adapters, and posts it back on-chain for your smart contract to use!
Oracles can define the parameters right in their job definitions as well (called the jobspec
), and you could just call the job without having to put in any parameters at all.
This has been a pretty deep dive on exactly how working with Chainlink nodes work, but with this, you now have a lot of the basic tools to build some amazing projects in the blockchain ecosystem.
As you can see, getting off-chain data in ethereum and any blockchain is easy, safe, and reliable with chainlink. Let’s see some building now!