Skip to content

Instantly share code, notes, and snippets.

@ajinux
Last active September 27, 2023 21:39
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ajinux/10b5733173613865a69a43439487c2fe to your computer and use it in GitHub Desktop.
Save ajinux/10b5733173613865a69a43439487c2fe to your computer and use it in GitHub Desktop.
This python script scrapes the fedex website and outputs the package details on giving the package tracking id as input

FEDEX SCRAPER

Question

Question Code:FEDEX
                    Write a Python script which will scrape the FEDEX website to obtain the tracking details of the given shipment tracking details. The output by the script should be in JSON format.
Input: 744668909687
Expected Output:
{ "tracking no": 744668909687,
"ship date": "Wed 19/07/2017",
"status": "delivered",
"scheduled delivery": "Mon 24/07/2017 16:21"
}
Input: 744668911595
Expected Output:
{ "Tracking no": 744668911595,
"Ship date“: "Fri 21/07/2017",
"Status": "In Transit",
"scheduled delivery": "Sat 29/07/2017 by 18:00"
}

Input and Output - 1

output1

Input and Output - 2

output2

Input and Output - 3

output3

dependencies

  • python 2.7
  • requests 2.11.1 (python package)
#!/usr/bin/python
#python2.7
import requests
import datetime
def attach_day(dt):
# dt format 7/24/2017
month, day, year = (int(x) for x in dt.split('/'))
date = datetime.date(year, month, day)
mdy = dt.split('/')
# format Mon 24/7/2017
return date.strftime('%A')[:3] + ' ' + '/'.join([mdy[1], mdy[0], mdy[2]])
def get_standard_time(tm):
# tm format 4:21 pm
tm = tm.strip()
if tm[5:] == 'am':
return tm
hour = int(tm.split(':')[0])
if hour != 12:
hour = hour + 12
time = str(hour) + ':' + tm.split(':')[1].split(' ')[0]
# format time 16:21
return time
def get_package_details(track_no):
try:
header = {
'Origin': 'https://www.fedex.com',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/59.0.3071.115 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Accept': '*/*',
'X-Requested-With': 'XMLHttpRequest',
'Referer': 'https://www.fedex.com/apps/fedextrack/?tracknumbers=%s&locale=en_CA&cntry_code=ca_english' % (
str(track_no)),
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.8,fr;q=0.6,ta;q=0.4,bn;q=0.2'
}
data = {
'action': 'trackpackages',
'data': '{"TrackPackagesRequest":{"appType":"WTRK","appDeviceType":"DESKTOP","uniqueKey":"",'
'"processingParameters":{},"trackingInfoList":[{"trackNumberInfo":{"trackingNumber":"%s",'
'"trackingQualifier":"","trackingCarrier":""}}]}}' % (
str(track_no)),
'format': 'json',
'locale': 'en_CA',
'version': '1'
}
url = "https://www.fedex.com/trackingCal/track"
print "Sending request ..."
response = requests.post(url, data=data, headers=header)
if response.status_code == 200:
print "response received successfully\n"
else:
print "request failed, error code : ",response.status_code
return
res_json = response.json()
if res_json['TrackPackagesResponse']['packageList'][0]['errorList'][0]['message'] != "":
print res_json['TrackPackagesResponse']['packageList'][0]['errorList'][0]['message']
# exists the function if package id is wrong
return
key_status = res_json['TrackPackagesResponse']['packageList'][0]['keyStatus']
# changes the scheduled delivery date and time w.r.t status
if key_status == "In transit":
schld_deli = attach_day(res_json['TrackPackagesResponse']['packageList'][0][
'displayEstDeliveryDt']) + " by " + get_standard_time(
res_json['TrackPackagesResponse']['packageList'][0]['displayEstDeliveryTm'])
else:
schld_deli = attach_day(
res_json['TrackPackagesResponse']['packageList'][0]['displayActDeliveryDt']) + " " + get_standard_time(
res_json['TrackPackagesResponse']['packageList'][0]['displayActDeliveryTm'])
result = {
'tracking_no': int(track_no),
'ship date': attach_day(res_json['TrackPackagesResponse']['packageList'][0]['displayShipDt']),
'status': res_json['TrackPackagesResponse']['packageList'][0]['keyStatus'],
'scheduled delivery': schld_deli
}
return result
except Exception as e:
print 'Error occurred : \n Error Message: ' + str(e)
# 744668909687, 744668911595
track_id = raw_input('Enter the tracking no : ')
print get_package_details(track_id)
@jaycupw
Copy link

jaycupw commented Nov 16, 2021

Hi,

I really like your FedEx-Scraper script - well done!

Two questions:

  1. When I view a tracking number of mine on the FedEx site, it has a delivery time of "10:25 AM". The delivery time in your script reads "22:25" which is 12 hours later. Bug or something else?
  2. How difficult would it be to add the delivery destination to the script? This is the info that is listed under "To" on the FedEx tracking page and it usually contains "City, State, Country".

Looking forward to your thoughts.

Thanks,
-- JW

@jaycupw
Copy link

jaycupw commented Nov 17, 2021

Figured out the timestamp issue in # 1 - sorry - overlooked that portion of the code.

@bertramm
Copy link

Forked and modified to work with UPS tracking ids. Needed to add an initial cross browser token retrieval.

https://gist.github.com/bertramm/9a96a7c7739727c83084505a9d875d35

@G2G2G2G
Copy link

G2G2G2G commented Feb 8, 2022

@mobbarley78110
Copy link

I used to get very good performance from the scraper but now it's painstakingly slow - like 4/5 seconds per tracking number. Wonder what changed?

@jaycupw
Copy link

jaycupw commented Mar 15, 2022

I've noticed a drastic slowdown as well. What used to take ~ 2-3 min now takes ~ 1.5 hours. The '.../trackingCal/...' link throws an error but, the requests seem to resolve - eventually. Would love to find out what's going on and how to remedy, if possible.

@jaycupw
Copy link

jaycupw commented Mar 21, 2022

From https://www.fedex.com/en-us/tracking.html:

"FedEx is constantly making improvements to our services to enhance the user experience and maintain security of customer data. Effective March 19, 2022, FedEx is making updates to the tracking experience on fedex.com to prevent automated scripts. For more information on the acceptable use of fedex.com, please refer to the fedex.com Terms of Use. Automated scripts on fedex.com will remain prohibited."

Can confirm that nothing works on my end as of 3/19/2022.

@mobbarley78110
Copy link

Another lead would be to use Selenium and Beautiful Soup. Pointers here: https://stackoverflow.com/questions/18817185/parsing-html-does-not-output-desired-datatracking-info-for-fedex

@jaycupw
Copy link

jaycupw commented Mar 21, 2022

Thanks. Tried several options but can't get around that 'https://www.fedex.com/trackingCal/track' appears dead. There may be other filters/blocks as well. Very surprised at this (imho, very bad) move since many business customers depend on automated tracking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment