DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Revolutionizing Financial Monitoring: Building a Team Dashboard With OpenObserve
  • Unlocking the Benefits of a Private API in AWS API Gateway
  • APIs for Logistics Orchestration: Designing for Compliance, Exceptions, and Edge Cases
  • Building Data Pipelines With Jira API

Trending

  • The Modern Data Stack Is Overrated — Here’s What Works
  • Unlocking AI Coding Assistants Part 4: Generate Spring Boot Application
  • Java’s Next Act: Native Speed for a Cloud-Native World
  • A Guide to Container Runtimes
  1. DZone
  2. Data Engineering
  3. Databases
  4. Working with the bit.ly API to shorten URLs

Working with the bit.ly API to shorten URLs

By 
Denzel D. user avatar
Denzel D.
·
Jun. 18, 10 · Interview
Likes (0)
Comment
Save
Tweet
Share
32.7K Views

Join the DZone community and get the full member experience.

Join For Free

Bit.ly is a quite popular URL shortening service. On Tiwtter, almost all of the links I see provided by the people I follow are posted as bit.ly shortcuts. If you’ve used a Twitter client, you probably already know that some of them (if not almost every single of them) offers URL shortening as a built-in capability.

Now, you can implement the same functionality, thanks to the fact that bit.ly offers a public API to do this. But let’s start with coding.

First of all, all data that is passed to the service is transferred via HTTP requests. The response generated by the service is by default formatted as a JSON document, however the developer can explicitly specify that XML data should be returned.  A request to the bit.ly shortening service requires authentication, and the username and API key are required to be passed as parameters. This means that in order to use the service, a bit.ly account is needed (it is free). The API key can be found here (http://bit.ly/account/your_api_key) once the user registered.

Shortening

The first (and probably the most important method) is the one that actually shortens the URL and it is called /v3/shorten. V3 at the beginning stands for the API version (that is 3.0 at the moment, so don’t worry about that).

This method accepts 5 parameters:

•    format – determines the output format for the request
•    longUrl –determines the long URL that needs to be shortened
•    domain – [optional] the domain used for shortening – either bit.ly or j.mp (default: bit.ly)
•    x_login – the user ID (although in the documentation it is indicated as optional, it is not)
•    x_apiKey – the user API key (although in the documentation it is indicated as optional, it is not)

Let’s look at the method I’ve written to shorten the URL:

enum Format
{
XML,
JSON,
TXT
}

enum Domain
{
BITLY,
JMP
}

string ShortenUrl(string longURL,
string username, string apiKey, Format format = Format.XML, Domain domain = Domain.BITLY)
{
string _domain;
string output;

// Build the domain string depending on the selected domain type
if (domain == Domain.BITLY)
_domain = "bit.ly";
else
_domain = "j.mp";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
string.Format(@"http://api.bit.ly/v3/shorten?login={0}&apiKey={1}&longUrl={2}&format={3}&domain={4}",
username, apiKey, HttpUtility.UrlEncode(longURL), format.ToString().ToLower(), _domain));

using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader (response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}

return output;
}

There are two enums that hold the possible data formats as well as the domain names. This is made for safety reasons – if I would pass these as string parameters, there is a higher chance the end-user will pass the wrong string, and then the function will fail.

The code is based on a single HttpWebRequest that creates a HTTP request to the URL that is built according to the data passed to it. Then, I am getting the response stream and passing the string representation to the returned string variable.

Notice the fact that I am explicitly returning a string value for this method. In fact, I could either return a JsonDocument instance (requires a third-party library to use this class) or XmlDocument. But since there are two possible formats for the request to handle, it is better to return this as a simple string and then let the developer decide what he wants to do next.

Once called, the function will return data similar to this:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<status_code>200</status_code>
<status_txt>OK</status_txt>
<data>
<url>http://j.mp/crnexS</url>
<hash>crnexS</hash>
<global_hash>msft</global_hash>
<long_url>http://www.microsoft.com</long_url>
<new_hash>0</new_hash>
</data>
</response>

Or this (for JSON):

{ "status_code": 200, "status_txt": "OK", "data": { "long_url": "http:\/\/www.microsoft.com", "url": "http:\/\/j.mp\/crnexS", "hash": "crnexS", "global_hash": "msft", "new_hash": 0 } }

Or this (for TXT):

http://j.mp/crnexS

I am using a custom domain here, but as you see – the format and domain are optional parameters. I can leave them with default values without actually passing them to the function, and then the only values that need to be indicated are the user ID, API key and the long URL.

Decoding

There is also a way to decode the URL to its initial state from what was the shortened one. The method is called /v3/expand and is used in a similar manner as the shortening one. In this method, I am also using the Format enum to specify the output format:

string DecodeUrl(string[] urlSet, string[] hashSet,
string username, string apiKey, Format format = Format.XML)
{
string output;

string URL = string.Format(@"http://api.bit.ly/v3/expand?login={0}&apiKey={1}&format={2}",
username, apiKey, format.ToString().ToLower());

if (urlSet != null)
{
foreach (string url in urlSet)
URL += "&shortUrl=" + HttpUtility.UrlEncode(url);
}

if (hashSet != null)
{
foreach (string hash in hashSet)
URL += "&hash=" + hash;
}

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);

using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}

return output;
}

It works a bit different though. As you can see, I am requesting the user to pass two arrays – one with URLs and one with hashes. One of them can be null, therefore the URL can be decoded either by the hash or by the shortened URL. The user can pass both arrays, and get a result similar to this:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<status_code>200</status_code>
<status_txt>OK</status_txt>
<data>
<entry>
<short_url>http://j.mp/crnexS</short_url>
<long_url>http://www.microsoft.com</long_url>
<user_hash>crnexS</user_hash>
<global_hash>msft</global_hash>
</entry>
<entry>
<hash>crnexS</hash>
<long_url>http://www.microsoft.com</long_url>
<user_hash>crnexS</user_hash>
<global_hash>msft</global_hash>
</entry>
</data>
</response>

 

The URLs are sanitized inside the function – I am not assuming that the user will pass the encoded URL. In fact, the developer should never assume that the user will pass the correct value – the code should be as foolproof as possible.

User validation

If you work on an application that depends on the URL shortening service, it would be a good idea to validate the user before making the API calls. Bit.ly provides a method for this as well and it is called /v3/validate. It only requires three parameters – the username, the API key and the output format (that is in fact optional).

The C# implementation for this method looks like this:

string ValidateUser(string username, string apiKey, string userToCheck, string keyToCheck, Format format = Format.XML)
{
string output;

string URL = string.Format(@"http://api.bit.ly/v3/validate?x_login={0}&x_apiKey={1}&login={2}&apiKey={3}&format={4}",
userToCheck, keyToCheck, username,apiKey, format.ToString().ToLower());

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);

using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}

return output;
}

 

A bit of confusion can be caused by the fact that there are x_ -prefixed copies of login and API key. You need to pass your ID and API key to verify someone else’s account validity. X_ -prefixed parameters represent the end user.

The output should look similar to this:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<status_code>200</status_code>
<status_txt>OK</status_txt>
<data>
<valid>1</valid>
</data>
</response>

 

Count clicks

Bit.ly provides click statistics, so once you shorten a URL, you can track its basic usage. Statistics are available through the /v3/clicks method. It doesn’t have a TXT output format, so you will have to avoid using that (or create a separate enum, that is the best choice).

The implementation for it looks like this:

string GetClicks(string[] urlSet, string[] hashSet,
string username, string apiKey, Format format = Format.XML)
{
string output;

string URL = string.Format(@"http://api.bit.ly/v3/clicks?login={0}&apiKey={1}&format={2}",
username, apiKey, format.ToString().ToLower());

if (urlSet != null)
{
foreach (string url in urlSet)
URL += "&shortUrl=" + HttpUtility.UrlEncode(url);
}

if (hashSet != null)
{
foreach (string hash in hashSet)
URL += "&hash=" + hash;
}

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);

using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}

return output;
}

Same as for the Expand method, an array of URLs and hash codes can be passed and statistics will be generated for multiple entries at once.

The response looks like this (in XML format):

<?xml version="1.0" encoding="UTF-8"?>
<response>
<status_code>200</status_code>
<data>
<clicks>
<short_url>http://j.mp/crnexS</short_url>
<global_hash>msft</global_hash>
<user_clicks>0</user_clicks>
<user_hash>crnexS</user_hash>
<global_clicks>2230</global_clicks>
</clicks>
<clicks>
<user_clicks>0</user_clicks>
<global_hash>msft</global_hash>
<hash>crnexS</hash>
<user_hash>crnexS</user_hash>
<global_clicks>2230</global_clicks>
</clicks>
</data>
<status_txt>OK</status_txt>
</response>

Note that the XML won’t be indented by default.

Check for PRO domain

Bit.ly offers pro, customizable domains. That means, that not only bit.ly and j.mp can be used for shortening, but user-defined domains as well. The /v3/bitly_pro_domain method allows to check whether a domain is bit.ly PRO-powered or not. It is very similar to the user validation method, but it accepts the domain name instead of the user credentials.

The C# implementation looks like this:

string CheckPro(string username, string apiKey, string domain, Format format = Format.XML)
{
string output;

string URL = string.Format(@"http://api.bit.ly/v3/bitly_pro_domain?login={0}&apiKey={1}&domain={2}&format={3}",
username, apiKey, domain, format.ToString().ToLower());

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);

using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}

return output;
}

Once called, the output looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<status_code>200</status_code>
<data>
<domain>nyti.ms</domain>
<bitly_pro_domain>1</bitly_pro_domain>
</data>
<status_txt>OK</status_txt>
</response>

 

URL lookup

Bit.ly also allows the lookup of long URLs. For example, you might want to find if there is an existing short URL for the existing long URL. To do this, there is the /v3/lookup method.

The implementation is quite simple and as other methods, it has the same base structure:

string Lookup(string username, string apiKey, string[] url, Format format = Format.XML)
{
string output;

string URL = string.Format(@"http://api.bit.ly/v3/lookup?login={0}&apiKey={1}&format={2}",
username, apiKey, format.ToString().ToLower());

foreach (string _url in url)
URL += "&url=" + HttpUtility.UrlEncode(_url);

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);

using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}

return output;
}

The XML response looks similar to this for a positive result (there is a URL found):

<?xml version="1.0" encoding="UTF-8"?>
<response>
<status_code>200</status_code>
<data>
<lookup>
<url>http://www.dreamincode.net</url>
<short_url>http://bit.ly/mviGY</short_url>
<global_hash>mviGY</global_hash>
</lookup>
</data>
<status_txt>OK</status_txt>
</response>

 

Notice that I can pass an array of URLs to be checked. Mind, though, that the maximum number of URLs that can be passed to the method is 15.

With the methods described above, you can harness the power of bit.ly and bring it to your .NET application (the code can easily be ported to any .NET-compatible programming language).

For official documentation, you can take a look here.

API

Opinions expressed by DZone contributors are their own.

Related

  • Revolutionizing Financial Monitoring: Building a Team Dashboard With OpenObserve
  • Unlocking the Benefits of a Private API in AWS API Gateway
  • APIs for Logistics Orchestration: Designing for Compliance, Exceptions, and Edge Cases
  • Building Data Pipelines With Jira API

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!